Merge branch 'main' into support-string-subclass-for-ruby

pull/13818/head
Iori Ikeda 12 months ago
commit 2d2796c4f9
  1. 4
      .bazelrc
  2. 48
      .github/workflows/janitor.yml
  3. 2
      .github/workflows/scorecard.yml
  4. 1
      .github/workflows/staleness_check.yml
  5. 8
      .github/workflows/staleness_refresh.yml
  6. 61
      .github/workflows/test_cpp.yml
  7. 2
      .github/workflows/test_php.yml
  8. 6
      .github/workflows/test_python.yml
  9. 32
      .github/workflows/test_upb.yml
  10. 40
      BUILD.bazel
  11. 2
      CMakeLists.txt
  12. 2
      Protobuf-C++.podspec
  13. 2
      Protobuf.podspec
  14. 38
      WORKSPACE
  15. 14
      bazel/BUILD
  16. 8
      bazel/build_defs.bzl
  17. 1
      bazel/py_proto_library.bzl
  18. 29
      benchmarks/benchmark.cc
  19. 29
      benchmarks/empty.proto
  20. 5
      build_defs/java_opts.bzl
  21. 46
      ci/common.bazelrc
  22. 1
      cmake/abseil-cpp.cmake
  23. 5
      cmake/install.cmake
  24. 15
      conformance/BUILD.bazel
  25. 8
      conformance/conformance_dart.dart
  26. 29
      conformance/conformance_objc.m
  27. 22
      conformance/conformance_python.py
  28. 12
      conformance/conformance_test.cc
  29. 3
      conformance/failure_list_python.txt
  30. 3
      conformance/failure_list_python_cpp.txt
  31. 6
      conformance/failure_list_python_upb.txt
  32. 6
      conformance/text_format_failure_list_python.txt
  33. 4
      conformance/text_format_failure_list_python_cpp.txt
  34. 11
      conformance/text_format_failure_list_python_upb.txt
  35. 2
      csharp/Google.Protobuf.Tools.nuspec
  36. 6
      csharp/src/Google.Protobuf.Test/FieldMaskTreeTest.cs
  37. BIN
      csharp/src/Google.Protobuf.Test/testprotos.pb
  38. 141
      csharp/src/Google.Protobuf/Compiler/Plugin.pb.cs
  39. 7
      csharp/src/Google.Protobuf/FieldMaskTree.cs
  40. 2
      csharp/src/Google.Protobuf/Google.Protobuf.csproj
  41. 374
      csharp/src/Google.Protobuf/Reflection/Descriptor.pb.cs
  42. 1
      docs/design/editions/README.md
  43. 150
      docs/design/editions/editions-feature-extension-layout.md
  44. 138
      docs/design/prototiller/prototiller-reqs-for-editions.md
  45. 5
      docs/options.md
  46. 47
      docs/third_party.md
  47. 6
      java/README.md
  48. 2
      java/bom/pom.xml
  49. 9
      java/core/BUILD.bazel
  50. 2
      java/core/pom.xml
  51. 40
      java/core/src/main/java/com/google/protobuf/AbstractMessage.java
  52. 17
      java/core/src/main/java/com/google/protobuf/Descriptors.java
  53. 66
      java/core/src/main/java/com/google/protobuf/FieldSet.java
  54. 29
      java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
  55. 6
      java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
  56. 128
      java/core/src/main/java/com/google/protobuf/RuntimeVersion.java
  57. 206
      java/core/src/main/java/com/google/protobuf/TextFormat.java
  58. 162
      java/core/src/test/java/com/google/protobuf/LazilyParsedMessageSetTest.java
  59. 138
      java/core/src/test/java/com/google/protobuf/RuntimeVersionTest.java
  60. 78
      java/core/src/test/java/com/google/protobuf/TextFormatTest.java
  61. 8
      java/core/src/test/java/com/google/protobuf/WireFormatTest.java
  62. 2
      java/kotlin-lite/pom.xml
  63. 2
      java/kotlin/pom.xml
  64. 2
      java/lite.md
  65. 4
      java/lite/pom.xml
  66. 6
      java/osgi/OsgiWrapper.java
  67. 4
      java/osgi/osgi.bzl
  68. 2
      java/pom.xml
  69. 2
      java/protoc/pom.xml
  70. 1
      java/util/BUILD.bazel
  71. 2
      java/util/pom.xml
  72. 29
      lua/def.c
  73. 2
      lua/lua_proto_library.bzl
  74. 29
      lua/main.c
  75. 29
      lua/msg.c
  76. 35
      lua/test.proto
  77. 31
      lua/test_upb.lua
  78. 29
      lua/upb.c
  79. 29
      lua/upb.h
  80. 30
      lua/upb.lua
  81. 29
      lua/upbc.cc
  82. 1
      objectivec/BUILD.bazel
  83. 3
      objectivec/GPBAny.pbobjc.h
  84. 8
      objectivec/GPBAny.pbobjc.m
  85. 9
      objectivec/GPBCodedOutputStream.m
  86. 7
      objectivec/GPBDictionary.m
  87. 3
      objectivec/GPBDuration.pbobjc.h
  88. 8
      objectivec/GPBDuration.pbobjc.m
  89. 9
      objectivec/GPBMessage.m
  90. 3
      objectivec/GPBTimestamp.pbobjc.h
  91. 8
      objectivec/GPBTimestamp.pbobjc.m
  92. 1
      objectivec/GPBUnknownFieldSet.m
  93. 18
      objectivec/GPBWellKnownTypes.h
  94. 11
      objectivec/GPBWellKnownTypes.m
  95. 23
      objectivec/Tests/GPBCodedOutputStreamTests.m
  96. 13
      objectivec/Tests/GPBMessageTests.m
  97. 12
      php/BUILD.bazel
  98. 7
      php/ext/google/protobuf/message.c
  99. 3156
      php/ext/google/protobuf/php-upb.c
  100. 2585
      php/ext/google/protobuf/php-upb.h
  101. Some files were not shown because too many files have changed in this diff Show More

@ -7,7 +7,6 @@ build:opt --compilation_mode=opt
build:san-common --config=dbg --strip=never --copt=-O0 --copt=-fno-omit-frame-pointer build:san-common --config=dbg --strip=never --copt=-O0 --copt=-fno-omit-frame-pointer
build:asan --config=san-common --copt=-fsanitize=address --linkopt=-fsanitize=address build:asan --config=san-common --copt=-fsanitize=address --linkopt=-fsanitize=address
build:asan --copt=-DADDRESS_SANITIZER=1
# ASAN hits ODR violations with shared linkage due to rules_proto. # ASAN hits ODR violations with shared linkage due to rules_proto.
build:asan --dynamic_mode=off build:asan --dynamic_mode=off
@ -15,14 +14,11 @@ build:msan --config=san-common --copt=-fsanitize=memory --linkopt=-fsanitize=mem
build:msan --copt=-fsanitize-memory-track-origins build:msan --copt=-fsanitize-memory-track-origins
build:msan --copt=-fsanitize-memory-use-after-dtor build:msan --copt=-fsanitize-memory-use-after-dtor
build:msan --action_env=MSAN_OPTIONS=poison_in_dtor=1 build:msan --action_env=MSAN_OPTIONS=poison_in_dtor=1
build:msan --copt=-DMEMORY_SANITIZER=1
build:tsan --config=san-common --copt=-fsanitize=thread --linkopt=-fsanitize=thread build:tsan --config=san-common --copt=-fsanitize=thread --linkopt=-fsanitize=thread
build:tsan --copt=-DTHREAD_SANITIZER=1
build:ubsan --config=san-common --copt=-fsanitize=undefined --linkopt=-fsanitize=undefined build:ubsan --config=san-common --copt=-fsanitize=undefined --linkopt=-fsanitize=undefined
build:ubsan --action_env=UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1 build:ubsan --action_env=UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1
build:ubsan --copt=-DUNDEFINED_SANITIZER=1
# Workaround for the fact that Bazel links with $CC, not $CXX # Workaround for the fact that Bazel links with $CC, not $CXX
# https://github.com/bazelbuild/bazel/issues/11122#issuecomment-613746748 # https://github.com/bazelbuild/bazel/issues/11122#issuecomment-613746748
build:ubsan --copt=-fno-sanitize=function --copt=-fno-sanitize=vptr build:ubsan --copt=-fno-sanitize=function --copt=-fno-sanitize=vptr

@ -28,3 +28,51 @@ jobs:
echo "Closing #$pr..." echo "Closing #$pr..."
gh pr close --comment "Auto-closing Copybara pull request" --delete-branch "$pr" gh pr close --comment "Auto-closing Copybara pull request" --delete-branch "$pr"
done done
stale-others:
name: Close stale non-copybara PRs and issues
runs-on: ubuntu-latest
permissions:
issues: write # allow the action to comment on, add labels to, and close issues
pull-requests: write # allow the action to comment on, add labels to, and close PRs
steps:
- uses: actions/stale@b69b346013879cedbf50c69f572cd85439a41936
with:
stale-issue-message: >
We triage inactive PRs and issues in order to make it easier to find
active work. If this issue should remain active or becomes active
again, please add a comment.
This issue is labeled `inactive` because the last activity was over
90 days ago.
close-issue-message: >
We triage inactive PRs and issues in order to make it easier to find
active work. If this issue should remain active or becomes active
again, please reopen it.
This issue was closed and archived because there has been no new
activity in the 14 days since the `inactive` label was added.
stale-pr-message: >
We triage inactive PRs and issues in order to make it easier to find
active work. If this PR should remain active, please add a comment.
This PR is labeled `inactive` because the last activity was over 90
days ago. This PR will be closed and archived after 14 additional
days without activity.
close-pr-message: >
We triage inactive PRs and issues in order to make it easier to find
active work. If this PR should remain active or becomes active
again, please reopen it.
This PR was closed and archived because there has been no new
activity in the 14 days since the `inactive` label was added.
stale-issue-label: 'inactive'
stale-pr-label: 'inactive'
exempt-issue-labels: 'help wanted'
days-before-stale: 90
days-before-close: 14
operations-per-run: 100

@ -32,7 +32,7 @@ jobs:
persist-credentials: false persist-credentials: false
- name: "Run analysis" - name: "Run analysis"
uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2 uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
with: with:
results_file: results.sarif results_file: results.sarif
results_format: sarif results_format: sarif

@ -54,6 +54,7 @@ jobs:
credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }}
bazel-cache: staleness bazel-cache: staleness
bash: > bash: >
set -ex;
if [[ -z $COMMIT_TRIGGERED_RUN || -z $MAIN_RUN ]]; then if [[ -z $COMMIT_TRIGGERED_RUN || -z $MAIN_RUN ]]; then
bazel query 'attr(tags, "staleness_test", //...)' | xargs bazel test $BAZEL_FLAGS || bazel query 'attr(tags, "staleness_test", //...)' | xargs bazel test $BAZEL_FLAGS ||
echo "Please run ./regenerate_stale_files.sh to regenerate stale files"; echo "Please run ./regenerate_stale_files.sh to regenerate stale files";

@ -30,10 +30,6 @@ jobs:
# failing then you may need to generate a fresh token. # failing then you may need to generate a fresh token.
token: ${{ secrets.BOT_ACCESS_TOKEN }} token: ${{ secrets.BOT_ACCESS_TOKEN }}
- name: Configure name and email address in Git - name: Configure name and email address in Git
run: git config user.name "Protobuf Team Bot" && git config user.email "protobuf-team-bot@google.com" run: cd ${{ github.workspace }} && git config user.name "Protobuf Team Bot" && git config user.email "protobuf-team-bot@google.com"
- name: Commit and push update - name: Commit and push update
uses: protocolbuffers/protobuf-ci/bazel@v2 run: cd ${{ github.workspace }} && ./ci/push_auto_update.sh
with:
credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }}
bazel-cache: staleness
bash: ci/push_auto_update.sh

@ -27,14 +27,14 @@ jobs:
include: include:
# Set defaults # Set defaults
- image: us-docker.pkg.dev/protobuf-build/containers/test/linux/sanitize@sha256:04cd765285bc52cbbf51d66c8c66d8603579cf0f19cc42df26b09d2c270541fb - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/sanitize@sha256:04cd765285bc52cbbf51d66c8c66d8603579cf0f19cc42df26b09d2c270541fb
- targets: //pkg/... //src/... @com_google_protobuf_examples//... - targets: //pkg/... //src/... @com_google_protobuf_examples//... //third_party/utf8_range/...
# Override cases with custom images # Override cases with custom images
- config: { name: "TCMalloc" } - config: { name: "TCMalloc" }
image: "us-docker.pkg.dev/protobuf-build/containers/test/linux/tcmalloc@sha256:bd39119d74b8a3fad4ae335d4cf5294e70384676331b7e19949459fc7a8d8328" image: "us-docker.pkg.dev/protobuf-build/containers/test/linux/tcmalloc@sha256:bd39119d74b8a3fad4ae335d4cf5294e70384676331b7e19949459fc7a8d8328"
targets: "//src/..." targets: "//src/... //third_party/utf8_range/..."
- config: { name: "aarch64" } - config: { name: "aarch64" }
targets: "//src/... //src/google/protobuf/compiler:protoc_aarch64_test" 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" image: "us-docker.pkg.dev/protobuf-build/containers/test/linux/emulation:aarch64-63dd26c0c7a808d92673a3e52e848189d4ab0f17"
name: Linux ${{ matrix.config.name }} name: Linux ${{ matrix.config.name }}
runs-on: ${{ matrix.config.runner || 'ubuntu-latest' }} runs-on: ${{ matrix.config.runner || 'ubuntu-latest' }}
@ -69,7 +69,7 @@ jobs:
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:${{ matrix.version }}-6.3.0-63dd26c0c7a808d92673a3e52e848189d4ab0f17
credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }}
bazel-cache: cpp_linux/gcc-${{ matrix.version }} bazel-cache: cpp_linux/gcc-${{ matrix.version }}
bazel: test //pkg/... //src/... @com_google_protobuf_examples//... bazel: test //pkg/... //src/... @com_google_protobuf_examples//... //third_party/utf8_range/...
linux-release: linux-release:
strategy: strategy:
@ -316,16 +316,16 @@ jobs:
- name: MacOS - name: MacOS
os: macos-12 os: macos-12
cache_key: macos-12 cache_key: macos-12
bazel: test //src/... bazel: test //src/... //third_party/utf8_range/...
- name: MacOS Apple Silicon (build only) - name: MacOS Apple Silicon (build only)
os: macos-12 os: macos-12
cache_key: macos-12-arm cache_key: macos-12-arm
# Current github runners are all Intel based, so just build/compile # Current github runners are all Intel based, so just build/compile
# for Apple Silicon to detect issues there. # for Apple Silicon to detect issues there.
bazel: build --cpu=darwin_arm64 //src/... bazel: build --cpu=darwin_arm64 //src/... //third_party/utf8_range/...
- name: Windows - name: Windows
os: windows-2019 os: windows-2022
cache_key: windows-2019 cache_key: windows-2022
bazel: test //src/... @com_google_protobuf_examples//... --test_tag_filters=-conformance --build_tag_filters=-conformance bazel: test //src/... @com_google_protobuf_examples//... --test_tag_filters=-conformance --build_tag_filters=-conformance
name: ${{ matrix.name }} Bazel name: ${{ matrix.name }} Bazel
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@ -351,14 +351,6 @@ jobs:
flags: -DCMAKE_CXX_STANDARD=14 flags: -DCMAKE_CXX_STANDARD=14
cache-prefix: macos-cmake cache-prefix: macos-cmake
- name: Windows CMake - name: Windows CMake
os: windows-2019
flags: >-
-G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF
-Dprotobuf_BUILD_SHARED_LIBS=OFF
-Dprotobuf_BUILD_EXAMPLES=ON
vsversion: '2019'
cache-prefix: windows-2019-cmake
- name: Windows CMake 2022
os: windows-2022 os: windows-2022
flags: >- flags: >-
-G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF
@ -366,29 +358,39 @@ jobs:
-Dprotobuf_BUILD_EXAMPLES=ON -Dprotobuf_BUILD_EXAMPLES=ON
vsversion: '2022' vsversion: '2022'
cache-prefix: windows-2022-cmake cache-prefix: windows-2022-cmake
- name: Windows CMake 32-bit - name: Windows CMake 2019
os: windows-2019 os: windows-2019
flags: >- flags: >-
-G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF
-Dprotobuf_BUILD_SHARED_LIBS=OFF
-Dprotobuf_BUILD_EXAMPLES=ON
vsversion: '2019' vsversion: '2019'
cache-prefix: windows-2019-cmake
# windows-2019 has python3.7 installed, which is incompatible with the latest gcloud
python-version: '3.8'
- name: Windows CMake 32-bit
os: windows-2022
flags: >-
-G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF
vsversion: '2022'
windows-arch: 'win32' windows-arch: 'win32'
cache-prefix: windows-2019-win32-cmake cache-prefix: windows-2022-win32-cmake
- name: Windows CMake Shared - name: Windows CMake Shared
os: windows-2019 os: windows-2022
flags: >- flags: >-
-G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF
-Dprotobuf_BUILD_SHARED_LIBS=ON -Dprotobuf_BUILD_SHARED_LIBS=ON
vsversion: '2019' vsversion: '2022'
cache-prefix: windows-2019-cmake cache-prefix: windows-2022-cmake
- name: Windows CMake Install - name: Windows CMake Install
os: windows-2019 os: windows-2022
install-flags: -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -Dprotobuf_BUILD_TESTS=OFF install-flags: -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -Dprotobuf_BUILD_TESTS=OFF
flags: >- flags: >-
-G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF
-Dprotobuf_REMOVE_INSTALLED_HEADERS=ON -Dprotobuf_REMOVE_INSTALLED_HEADERS=ON
-Dprotobuf_BUILD_PROTOBUF_BINARIES=OFF -Dprotobuf_BUILD_PROTOBUF_BINARIES=OFF
vsversion: '2019' vsversion: '2022'
cache-prefix: windows-2019-cmake cache-prefix: windows-2022-cmake
name: ${{ matrix.name }} name: ${{ matrix.name }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
@ -405,6 +407,17 @@ jobs:
arch: ${{ matrix.windows-arch || 'x64' }} arch: ${{ matrix.windows-arch || 'x64' }}
vsversion: ${{ matrix.vsversion }} vsversion: ${{ matrix.vsversion }}
# Workaround for incompatibility between gcloud and windows-2019 runners.
- name: Install Python
if: ${{ matrix.python-version }}
uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0
with:
python-version: ${{ matrix.python-version }}
- name: Use custom python for gcloud
if: ${{ matrix.python-version }}
run: echo "CLOUDSDK_PYTHON=${Python3_ROOT_DIR}\\python3" >> $GITHUB_ENV
shell: bash
- name: Setup sccache - name: Setup sccache
uses: protocolbuffers/protobuf-ci/sccache@v2 uses: protocolbuffers/protobuf-ci/sccache@v2
with: with:

@ -150,7 +150,7 @@ jobs:
strategy: strategy:
fail-fast: false # Don't cancel all jobs if one fails. fail-fast: false # Don't cancel all jobs if one fails.
matrix: matrix:
version: ['8.0'] version: ['8.2']
name: MacOS PHP ${{ matrix.version }} name: MacOS PHP ${{ matrix.version }}
runs-on: macos-12 runs-on: macos-12

@ -17,7 +17,8 @@ jobs:
fail-fast: false # Don't cancel all jobs if one fails. fail-fast: false # Don't cancel all jobs if one fails.
matrix: matrix:
type: [ Pure, C++] type: [ Pure, C++]
version: ["3.8", "3.9", "3.10", "3.11" ] # TODO: b/309627662 - Add coverage for Python 3.12.
version: ["3.8", "3.9", "3.10", "3.11"]
include: include:
- type: Pure - type: Pure
targets: //python/... //python:python_version_test targets: //python/... //python:python_version_test
@ -55,7 +56,7 @@ jobs:
matrix: matrix:
type: [ Pure, C++] type: [ Pure, C++]
# TODO Consider expanding this set of versions. # TODO Consider expanding this set of versions.
version: [ "3.11" ] version: [ "3.12" ]
include: include:
- type: Pure - type: Pure
targets: //python/... //python:python_version_test targets: //python/... //python:python_version_test
@ -76,6 +77,7 @@ jobs:
with: with:
python-version: ${{ matrix.version }} python-version: ${{ matrix.version }}
cache: pip cache: pip
cache-dependency-path: 'python/requirements.txt'
- name: Validate version - name: Validate version
run: python3 --version | grep ${{ matrix.version }} || (echo "Invalid Python version - $(python3 --version)" && exit 1) run: python3 --version | grep ${{ matrix.version }} || (echo "Invalid Python version - $(python3 --version)" && exit 1)

@ -20,6 +20,7 @@ jobs:
- { name: "Fastbuild" } - { name: "Fastbuild" }
- { name: "Optimized", flags: "-c opt" } - { name: "Optimized", flags: "-c opt" }
- { name: "FastTable", flags: "--//upb:fasttable_enabled=true" } - { name: "FastTable", flags: "--//upb:fasttable_enabled=true" }
- { name: "FastTable ASAN", flags: "--//upb:fasttable_enabled=true --config=asan", exclude-targets: "-//benchmarks:benchmark -//python/..." }
- { name: "ASAN", flags: "--config=asan -c dbg", exclude-targets: "-//benchmarks:benchmark -//python/..." } - { name: "ASAN", flags: "--config=asan -c dbg", exclude-targets: "-//benchmarks:benchmark -//python/..." }
- { name: "UBSAN", flags: "--config=ubsan -c dbg", exclude-targets: "-//benchmarks:benchmark -//python/... -//lua/..." } - { name: "UBSAN", flags: "--config=ubsan -c dbg", exclude-targets: "-//benchmarks:benchmark -//python/... -//lua/..." }
- { name: "32-bit", flags: "--copt=-m32 --linkopt=-m32", exclude-targets: "-//benchmarks:benchmark -//python/..." } - { name: "32-bit", flags: "--copt=-m32 --linkopt=-m32", exclude-targets: "-//benchmarks:benchmark -//python/..." }
@ -64,19 +65,23 @@ jobs:
strategy: strategy:
fail-fast: false # Don't cancel all jobs if one fails. fail-fast: false # Don't cancel all jobs if one fails.
name: Windows name: Windows
runs-on: windows-2019 runs-on: windows-2022
steps: steps:
- name: Checkout pending changes - name: Checkout pending changes
uses: protocolbuffers/protobuf-ci/checkout@v2 uses: protocolbuffers/protobuf-ci/checkout@v2
with: with:
ref: ${{ inputs.safe-checkout }} ref: ${{ inputs.safe-checkout }}
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0
with:
cache: pip
cache-dependency-path: 'python/requirements.txt'
- name: Run tests - name: Run tests
uses: protocolbuffers/protobuf-ci/bazel@v2 uses: protocolbuffers/protobuf-ci/bazel@v2
with: with:
credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }}
bazel-cache: "upb-bazel-windows" bazel-cache: "upb-bazel-windows"
bazel: test --cxxopt=/std:c++17 --host_cxxopt=/std:c++17 //upb/... //upb_generator/... //python/... //protos/... //protos_generator/... bazel: test --cxxopt=/std:c++17 --host_cxxopt=/std:c++17 //upb/... //upb_generator/... //python/... //protos/... //protos_generator/...
exclude-targets: -//python:conformance_test -//upb:def_builder_test exclude-targets: -//python:conformance_test -//upb/reflection:def_builder_test
macos: macos:
strategy: strategy:
@ -92,6 +97,10 @@ jobs:
uses: protocolbuffers/protobuf-ci/checkout@v2 uses: protocolbuffers/protobuf-ci/checkout@v2
with: with:
ref: ${{ inputs.safe-checkout }} ref: ${{ inputs.safe-checkout }}
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0
with:
cache: pip
cache-dependency-path: 'python/requirements.txt'
- name: Run tests - name: Run tests
uses: protocolbuffers/protobuf-ci/bazel@v2 uses: protocolbuffers/protobuf-ci/bazel@v2
with: with:
@ -162,23 +171,24 @@ jobs:
# coverage. # coverage.
- { os: ubuntu-latest, python-version: "3.8", architecture: x64, type: 'binary' } - { os: ubuntu-latest, python-version: "3.8", architecture: x64, type: 'binary' }
- { os: macos-11, 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.11", architecture: x64, type: 'binary' } - { os: ubuntu-latest, python-version: "3.12", architecture: x64, type: 'binary' }
- { os: macos-12, python-version: "3.11", 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: ubuntu-latest, python-version: "3.8", architecture: x64, type: 'source' }
- { os: macos-11, 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.11", architecture: x64, type: 'source' } - { os: ubuntu-latest, python-version: "3.12", architecture: x64, type: 'source' }
- { os: macos-12, python-version: "3.11", architecture: x64, type: 'source' } - { os: macos-12, python-version: "3.12", architecture: x64, type: 'source' }
# Windows uses the full API up until Python 3.10, so each of these # Windows uses the full API up until Python 3.10.
# jobs tests a distinct binary wheel.
- { os: windows-2019, python-version: "3.8", architecture: x86, type: 'binary' } - { 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.9", architecture: x86, type: 'binary' }
- { os: windows-2019, python-version: "3.10", 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.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.8", architecture: x64, type: 'binary' }
- { os: windows-2019, python-version: "3.9", architecture: x64, type: 'binary' } - { 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.10", architecture: x64, type: 'binary' }
- { os: windows-2019, python-version: "3.11", 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' }
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
if: ${{ github.event_name != 'pull_request_target' }} if: ${{ github.event_name != 'pull_request_target' }}
defaults: defaults:
@ -195,7 +205,7 @@ jobs:
with: with:
name: requirements name: requirements
path: requirements path: requirements
- uses: actions/setup-python@v2 - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
architecture: ${{ matrix.architecture }} architecture: ${{ matrix.architecture }}
@ -239,7 +249,7 @@ jobs:
strategy: strategy:
fail-fast: false # Don't cancel all jobs if one fails. fail-fast: false # Don't cancel all jobs if one fails.
matrix: matrix:
python-version: ["3.8", "3.11"] python-version: ["3.8", "3.12"]
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ github.event_name != 'pull_request_target' }} if: ${{ github.event_name != 'pull_request_target' }}
steps: steps:
@ -250,7 +260,7 @@ jobs:
path: wheels path: wheels
- name: Delete Binary Wheels - name: Delete Binary Wheels
run: find wheels -type f | grep -v none-any | xargs rm run: find wheels -type f | grep -v none-any | xargs rm
- uses: actions/setup-python@v2 - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: Setup Python venv - name: Setup Python venv

@ -5,7 +5,7 @@ load("@rules_java//java:defs.bzl", "java_lite_proto_library", "java_proto_librar
load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix") load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain", "proto_library") load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain", "proto_library")
load("//build_defs:cpp_opts.bzl", "COPTS", "LINK_OPTS") load("//build_defs:cpp_opts.bzl", "COPTS", "LINK_OPTS")
load(":protobuf.bzl", "internal_objc_proto_library", "internal_php_proto_library", "internal_py_proto_library", "internal_ruby_proto_library") load(":protobuf.bzl", "internal_objc_proto_library", "internal_php_proto_library", "internal_py_proto_library")
licenses(["notice"]) licenses(["notice"])
@ -150,17 +150,6 @@ filegroup(
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )
internal_ruby_proto_library(
name = "well_known_ruby_protos",
srcs = [":well_known_protos"],
default_runtime = "",
includes = ["src"],
visibility = [
"//conformance:__pkg__",
"//ruby:__subpackages__",
],
)
################################################################################ ################################################################################
# Protocol Buffers Compiler # Protocol Buffers Compiler
################################################################################ ################################################################################
@ -524,33 +513,6 @@ internal_php_proto_library(
], ],
) )
internal_ruby_proto_library(
name = "test_messages_proto2_ruby_proto",
testonly = 1,
srcs = ["//src/google/protobuf:test_messages_proto2.proto"],
includes = ["src/google/protobuf"],
visibility = [
"//conformance:__pkg__",
"//ruby:__subpackages__",
],
)
internal_ruby_proto_library(
name = "test_messages_proto3_ruby_proto",
testonly = 1,
srcs = ["//src/google/protobuf:test_messages_proto3.proto"],
includes = [
"src/google/protobuf",
# The above must come first.
"src",
],
visibility = [
"//conformance:__pkg__",
"//ruby:__subpackages__",
],
deps = [":well_known_ruby_protos"],
)
filegroup( filegroup(
name = "bzl_srcs", name = "bzl_srcs",
srcs = glob(["**/*.bzl"]), srcs = glob(["**/*.bzl"]),

@ -79,7 +79,7 @@ if (protobuf_BUILD_SHARED_LIBS)
endif () endif ()
# Version metadata # Version metadata
set(protobuf_VERSION_STRING "4.24.0") set(protobuf_VERSION_STRING "4.25.0")
set(protobuf_DESCRIPTION "Protocol Buffers") set(protobuf_DESCRIPTION "Protocol Buffers")
set(protobuf_CONTACT "protobuf@googlegroups.com") set(protobuf_CONTACT "protobuf@googlegroups.com")

@ -1,6 +1,6 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'Protobuf-C++' s.name = 'Protobuf-C++'
s.version = '4.24.0' s.version = '4.25.0'
s.summary = 'Protocol Buffers v3 runtime library for C++.' s.summary = 'Protocol Buffers v3 runtime library for C++.'
s.homepage = 'https://github.com/google/protobuf' s.homepage = 'https://github.com/google/protobuf'
s.license = 'BSD-3-Clause' s.license = 'BSD-3-Clause'

@ -5,7 +5,7 @@
# dependent projects use the :git notation to refer to the library. # dependent projects use the :git notation to refer to the library.
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'Protobuf' s.name = 'Protobuf'
s.version = '3.24.0' s.version = '3.25.0'
s.summary = 'Protocol Buffers v.3 runtime library for Objective-C.' s.summary = 'Protocol Buffers v.3 runtime library for Objective-C.'
s.homepage = 'https://github.com/protocolbuffers/protobuf' s.homepage = 'https://github.com/protocolbuffers/protobuf'
s.license = 'BSD-3-Clause' s.license = 'BSD-3-Clause'

@ -1,5 +1,10 @@
workspace(name = "com_google_protobuf") workspace(name = "com_google_protobuf")
# An explicit self-reference to work around changes in Bazel 7.0
# See https://github.com/bazelbuild/bazel/issues/19973#issuecomment-1787814450
# buildifier: disable=duplicated-name
local_repository(name = "com_google_protobuf", path = ".")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
local_repository( local_repository(
@ -12,6 +17,10 @@ load("//:protobuf_deps.bzl", "PROTOBUF_MAVEN_ARTIFACTS", "protobuf_deps")
protobuf_deps() protobuf_deps()
load("@rules_python//python:repositories.bzl", "py_repositories")
py_repositories()
# Bazel platform rules. # Bazel platform rules.
http_archive( http_archive(
name = "platforms", name = "platforms",
@ -82,6 +91,15 @@ load("@io_bazel_rules_kotlin//kotlin:core.bzl", "kt_register_toolchains")
kt_register_toolchains() kt_register_toolchains()
http_archive(
name = "rules_ruby",
urls = [
"https://github.com/protocolbuffers/rules_ruby/archive/b7f3e9756f3c45527be27bc38840d5a1ba690436.zip"
],
strip_prefix = "rules_ruby-b7f3e9756f3c45527be27bc38840d5a1ba690436",
sha256 = "347927fd8de6132099fcdc58e8f7eab7bde4eb2fd424546b9cd4f1c6f8f8bad8",
)
load("@rules_ruby//ruby:defs.bzl", "ruby_runtime") load("@rules_ruby//ruby:defs.bzl", "ruby_runtime")
ruby_runtime("system_ruby") ruby_runtime("system_ruby")
@ -152,21 +170,27 @@ load("@pip_deps//:requirements.bzl", "install_deps")
install_deps() install_deps()
load("@utf8_range//:workspace_deps.bzl", "utf8_range_deps")
utf8_range_deps()
http_archive( http_archive(
name = "rules_fuzzing", name = "rules_fuzzing",
sha256 = "d9002dd3cd6437017f08593124fdd1b13b3473c7b929ceb0e60d317cb9346118", sha256 = "ff52ef4845ab00e95d29c02a9e32e9eff4e0a4c9c8a6bcf8407a2f19eb3f9190",
strip_prefix = "rules_fuzzing-0.3.2", strip_prefix = "rules_fuzzing-0.4.1",
urls = ["https://github.com/bazelbuild/rules_fuzzing/archive/v0.3.2.zip"], urls = ["https://github.com/bazelbuild/rules_fuzzing/releases/download/v0.4.1/rules_fuzzing-0.4.1.zip"],
patches = ["//third_party:rules_fuzzing.patch"],
patch_args = ["-p1"],
) )
load("@rules_fuzzing//fuzzing:repositories.bzl", "rules_fuzzing_dependencies") load("@rules_fuzzing//fuzzing:repositories.bzl", "rules_fuzzing_dependencies")
rules_fuzzing_dependencies() rules_fuzzing_dependencies()
load("@rules_fuzzing//fuzzing:init.bzl", "rules_fuzzing_init")
rules_fuzzing_init()
load("@fuzzing_py_deps//:requirements.bzl", fuzzing_py_deps_install_deps = "install_deps")
fuzzing_py_deps_install_deps()
bind( bind(
name = "python_headers", name = "python_headers",
actual = "@system_python//:python_headers", actual = "@system_python//:python_headers",

@ -7,6 +7,7 @@
load("@rules_python//python:defs.bzl", "py_binary") load("@rules_python//python:defs.bzl", "py_binary")
load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load("@bazel_skylib//lib:selects.bzl", "selects")
# begin:google_only # begin:google_only
# package(default_applicable_licenses = ["//upb:license"]) # package(default_applicable_licenses = ["//upb:license"])
@ -14,6 +15,16 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
licenses(["notice"]) licenses(["notice"])
# begin:google_only
# selects.config_setting_group(
# name = "android_opt",
# match_all = [
# "//tools/cc_target_os:android",
# "//tools/compilation_mode:opt",
# ],
# )
# end:google_only
py_binary( py_binary(
name = "amalgamate", name = "amalgamate",
srcs = ["amalgamate.py"], srcs = ["amalgamate.py"],
@ -26,6 +37,9 @@ py_binary(
bzl_library( bzl_library(
name = "py_proto_library_bzl", name = "py_proto_library_bzl",
srcs = ["py_proto_library.bzl"], srcs = ["py_proto_library.bzl"],
deps = [
"@rules_python//python:py_info_bzl",
],
) )
bzl_library( bzl_library(

@ -30,12 +30,20 @@ _DEFAULT_COPTS.extend([
UPB_DEFAULT_CPPOPTS = select({ UPB_DEFAULT_CPPOPTS = select({
"//upb:windows": [], "//upb:windows": [],
# begin:google_only
# # Override default -Oz for release builds on Android.
# "//bazel:android_opt": _DEFAULT_CPPOPTS + ["-O2"],
# end:google_only
"//conditions:default": _DEFAULT_CPPOPTS, "//conditions:default": _DEFAULT_CPPOPTS,
}) })
UPB_DEFAULT_COPTS = select({ UPB_DEFAULT_COPTS = select({
"//upb:windows": [], "//upb:windows": [],
"//upb:fasttable_enabled_setting": ["-std=gnu99", "-DUPB_ENABLE_FASTTABLE"], "//upb:fasttable_enabled_setting": ["-std=gnu99", "-DUPB_ENABLE_FASTTABLE"],
# begin:google_only
# # Override default -Oz for release builds on Android.
# "//bazel:android_opt": _DEFAULT_COPTS + ["-O2"],
# end:google_only
"//conditions:default": _DEFAULT_COPTS, "//conditions:default": _DEFAULT_COPTS,
}) })

@ -15,6 +15,7 @@ But it hasn't been deeply tested or reviewed, and upb should not be in the
business of vending py_proto_library(), so we keep it private to upb. business of vending py_proto_library(), so we keep it private to upb.
""" """
load("@rules_python//python:py_info.bzl", "PyInfo")
load("@bazel_skylib//lib:paths.bzl", "paths") load("@bazel_skylib//lib:paths.bzl", "paths")
# begin:github_only # begin:github_only

@ -1,32 +1,9 @@
// Protocol Buffers - Google's data interchange format // Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved. // Copyright 2023 Google LLC. All rights reserved.
// https://developers.google.com/protocol-buffers/
// //
// Redistribution and use in source and binary forms, with or without // Use of this source code is governed by a BSD-style
// modification, are permitted provided that the following conditions are // license that can be found in the LICENSE file or at
// met: // https://developers.google.com/open-source/licenses/bsd
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, 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.
#include <benchmark/benchmark.h> #include <benchmark/benchmark.h>

@ -1,32 +1,9 @@
// Protocol Buffers - Google's data interchange format // Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved. // Copyright 2023 Google LLC. All rights reserved.
// https://developers.google.com/protocol-buffers/
// //
// Redistribution and use in source and binary forms, with or without // Use of this source code is governed by a BSD-style
// modification, are permitted provided that the following conditions are // license that can be found in the LICENSE file or at
// met: // https://developers.google.com/open-source/licenses/bsd
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, 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.
syntax = "proto3"; syntax = "proto3";

@ -27,6 +27,7 @@ def protobuf_java_library(**kwargs):
) )
def protobuf_versioned_java_library( def protobuf_versioned_java_library(
automatic_module_name,
bundle_description, bundle_description,
bundle_name, bundle_name,
bundle_symbolic_name, bundle_symbolic_name,
@ -44,6 +45,9 @@ def protobuf_versioned_java_library(
Args: Args:
bundle_description: (required) The Bundle-Description header defines a short bundle_description: (required) The Bundle-Description header defines a short
description of this bundle. 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_name: (required) The Bundle-Name header defines a readable name for this
bundle. This should be a short, human-readable name that can bundle. This should be a short, human-readable name that can
contain spaces. contain spaces.
@ -65,6 +69,7 @@ def protobuf_versioned_java_library(
""" """
osgi_java_library( osgi_java_library(
javacopts = JAVA_OPTS, javacopts = JAVA_OPTS,
automatic_module_name = automatic_module_name,
bundle_doc_url = BUNDLE_DOC_URL, bundle_doc_url = BUNDLE_DOC_URL,
bundle_license = BUNDLE_LICENSE, bundle_license = BUNDLE_LICENSE,
bundle_version = PROTOBUF_JAVA_VERSION, bundle_version = PROTOBUF_JAVA_VERSION,

@ -1,6 +1,3 @@
# Fail if a glob doesn't match anything (https://github.com/bazelbuild/bazel/issues/8195)
build --incompatible_disallow_empty_glob
build:dbg --compilation_mode=dbg build:dbg --compilation_mode=dbg
build:opt --compilation_mode=opt build:opt --compilation_mode=opt
@ -8,7 +5,6 @@ build:opt --compilation_mode=opt
build:san-common --config=dbg --strip=never --copt=-O0 --copt=-fno-omit-frame-pointer build:san-common --config=dbg --strip=never --copt=-O0 --copt=-fno-omit-frame-pointer
build:asan --config=san-common --copt=-fsanitize=address --linkopt=-fsanitize=address build:asan --config=san-common --copt=-fsanitize=address --linkopt=-fsanitize=address
build:asan --copt=-DADDRESS_SANITIZER=1
# ASAN hits ODR violations with shared linkage due to rules_proto. # ASAN hits ODR violations with shared linkage due to rules_proto.
build:asan --dynamic_mode=off build:asan --dynamic_mode=off
@ -16,7 +12,6 @@ build:msan --config=san-common --copt=-fsanitize=memory --linkopt=-fsanitize=mem
build:msan --copt=-fsanitize-memory-track-origins build:msan --copt=-fsanitize-memory-track-origins
build:msan --copt=-fsanitize-memory-use-after-dtor build:msan --copt=-fsanitize-memory-use-after-dtor
build:msan --action_env=MSAN_OPTIONS=poison_in_dtor=1 build:msan --action_env=MSAN_OPTIONS=poison_in_dtor=1
build:msan --copt=-DMEMORY_SANITIZER=1
# Use our instrumented LLVM libc++ in Kokoro. # Use our instrumented LLVM libc++ in Kokoro.
build:docker-msan --config=msan build:docker-msan --config=msan
@ -26,11 +21,48 @@ build:docker-msan --cxxopt=-stdlib=libc++ --linkopt=-stdlib=libc++
build:tsan --config=san-common --copt=-fsanitize=thread --linkopt=-fsanitize=thread build:tsan --config=san-common --copt=-fsanitize=thread --linkopt=-fsanitize=thread
build:tsan --copt=-DTHREAD_SANITIZER=1
build:ubsan --config=san-common --copt=-fsanitize=undefined --linkopt=-fsanitize=undefined build:ubsan --config=san-common --copt=-fsanitize=undefined --linkopt=-fsanitize=undefined
build:ubsan --action_env=UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1 build:ubsan --action_env=UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1
build:ubsan --copt=-DUNDEFINED_SANITIZER=1
# Workaround for the fact that Bazel links with $CC, not $CXX # Workaround for the fact that Bazel links with $CC, not $CXX
# https://github.com/bazelbuild/bazel/issues/11122#issuecomment-613746748 # https://github.com/bazelbuild/bazel/issues/11122#issuecomment-613746748
build:ubsan --copt=-fno-sanitize=function --copt=-fno-sanitize=vptr build:ubsan --copt=-fno-sanitize=function --copt=-fno-sanitize=vptr
# Build with all --incompatible flags that we can. This helps us prepare for
# upcoming breaking changes in Bazel. This list was generated for Bazel 6 by
# running bazelisk with the --migrate flag and filtering out all flags that
# default to true or are deprecated.
build --incompatible_check_sharding_support
build --incompatible_default_to_explicit_init_py
build --incompatible_disable_native_android_rules
build --incompatible_disable_runtimes_filegroups
build --incompatible_disable_target_provider_fields
build --incompatible_disallow_empty_glob
build --incompatible_dont_use_javasourceinfoprovider
build --incompatible_enable_android_toolchain_resolution
build --incompatible_enable_apple_toolchain_resolution
build --incompatible_exclusive_test_sandboxed
build --incompatible_remote_output_paths_relative_to_input_root
build --incompatible_remote_use_new_exit_code_for_lost_inputs
build --incompatible_sandbox_hermetic_tmp
build --incompatible_struct_has_no_methods
build --incompatible_top_level_aspects_require_providers
build --incompatible_use_cc_configure_from_rules_cc
build --incompatible_use_host_features
# We cannot yet build successfully with the following flags:
# --incompatible_check_testonly_for_output_files
# --incompatible_config_setting_private_default_visibility
# --incompatible_disable_starlark_host_transitions
# --incompatible_disallow_struct_provider_syntax
# --incompatible_no_implicit_file_export
# --incompatible_no_rule_outputs_param
# --incompatible_stop_exporting_language_modules
# --incompatible_strict_action_env
# --incompatible_visibility_private_attributes_at_definition
# We might be compatible with these flags, but they are not available in all
# Bazel versions we are currently using:
# --incompatible_disable_objc_library_transition
# --incompatible_fail_on_unknown_attributes
# --incompatible_merge_fixed_and_default_shell_env

@ -72,6 +72,7 @@ else()
absl::flat_hash_set absl::flat_hash_set
absl::function_ref absl::function_ref
absl::hash absl::hash
absl::if_constexpr
absl::layout absl::layout
absl::log_initialize absl::log_initialize
absl::log_severity absl::log_severity

@ -78,7 +78,10 @@ foreach(_header ${protobuf_HEADERS})
elseif (_find_nosrc GREATER -1) elseif (_find_nosrc GREATER -1)
set(_from_dir "${protobuf_SOURCE_DIR}") set(_from_dir "${protobuf_SOURCE_DIR}")
endif() endif()
string(REPLACE "${_from_dir}" "" _header ${_header}) # On some platforms `_form_dir` ends up being just "protobuf", which can
# easily match multiple times in our paths. We force it to only replace
# prefixes to avoid this case.
string(REGEX REPLACE "^${_from_dir}" "" _header ${_header})
get_filename_component(_extract_from "${_from_dir}/${_header}" ABSOLUTE) get_filename_component(_extract_from "${_from_dir}/${_header}" ABSOLUTE)
get_filename_component(_extract_name ${_header} NAME) get_filename_component(_extract_name ${_header} NAME)
get_filename_component(_extract_to "${CMAKE_INSTALL_INCLUDEDIR}/${_header}" DIRECTORY) get_filename_component(_extract_to "${CMAKE_INSTALL_INCLUDEDIR}/${_header}" DIRECTORY)

@ -2,7 +2,8 @@
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_proto_library", "objc_library") load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_proto_library", "objc_library")
load("@rules_ruby//ruby:defs.bzl", "ruby_binary") 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("//ruby:defs.bzl", "internal_ruby_proto_library")
load("//:protobuf.bzl", "internal_csharp_proto_library", "internal_objc_proto_library", "internal_php_proto_library", "internal_py_proto_library")
load("//build_defs:internal_shell.bzl", "inline_sh_binary") load("//build_defs:internal_shell.bzl", "inline_sh_binary")
load( load(
"@rules_pkg//:mappings.bzl", "@rules_pkg//:mappings.bzl",
@ -22,6 +23,7 @@ exports_files([
"failure_list_php_c.txt", "failure_list_php_c.txt",
"failure_list_python.txt", "failure_list_python.txt",
"failure_list_python_cpp.txt", "failure_list_python_cpp.txt",
"failure_list_python_upb.txt",
"failure_list_ruby.txt", "failure_list_ruby.txt",
"failure_list_jruby.txt", "failure_list_jruby.txt",
"failure_list_jruby_ffi.txt", "failure_list_jruby_ffi.txt",
@ -33,6 +35,7 @@ exports_files([
"text_format_failure_list_php_c.txt", "text_format_failure_list_php_c.txt",
"text_format_failure_list_python.txt", "text_format_failure_list_python.txt",
"text_format_failure_list_python_cpp.txt", "text_format_failure_list_python_cpp.txt",
"text_format_failure_list_python_upb.txt",
"text_format_failure_list_ruby.txt", "text_format_failure_list_ruby.txt",
"text_format_failure_list_jruby.txt", "text_format_failure_list_jruby.txt",
"text_format_failure_list_jruby_ffi.txt", "text_format_failure_list_jruby_ffi.txt",
@ -141,7 +144,6 @@ cc_library(
includes = ["."], includes = ["."],
deps = [ deps = [
":conformance_cc_proto", ":conformance_cc_proto",
"//src/google/protobuf:descriptor_legacy",
"//src/google/protobuf/util:differencer", "//src/google/protobuf/util:differencer",
"//src/google/protobuf/util:json_util", "//src/google/protobuf/util:json_util",
"//src/google/protobuf/util:type_resolver_util", "//src/google/protobuf/util:type_resolver_util",
@ -261,8 +263,8 @@ py_binary(
deps = [ deps = [
":conformance_py_proto", ":conformance_py_proto",
"//:protobuf_python", "//:protobuf_python",
"//python:test_messages_proto2_py_proto", "//python:_message", # Make upb visible if we need it.
"//python:test_messages_proto3_py_proto", "//python:conformance_test_py_proto",
], ],
) )
@ -326,6 +328,8 @@ objc_library(
":conformance_objc_proto", ":conformance_objc_proto",
"//:test_messages_proto2_objc_proto", "//:test_messages_proto2_objc_proto",
"//:test_messages_proto3_objc_proto", "//:test_messages_proto3_objc_proto",
"//src/google/protobuf/editions:test_messages_proto2_editions_objc_proto",
"//src/google/protobuf/editions:test_messages_proto3_editions_objc_proto",
], ],
) )
@ -345,8 +349,7 @@ ruby_binary(
visibility = ["//ruby:__subpackages__"], visibility = ["//ruby:__subpackages__"],
deps = [ deps = [
":conformance_ruby_proto", ":conformance_ruby_proto",
"//:test_messages_proto2_ruby_proto", "//ruby:conformance_test_ruby_proto",
"//:test_messages_proto3_ruby_proto",
], ],
) )

@ -1,6 +1,5 @@
import 'dart:io'; import 'dart:io';
import 'package:pb_runtime/ffi/bytes.dart';
import 'package:pb_runtime/pb_runtime.dart' as pb; import 'package:pb_runtime/pb_runtime.dart' as pb;
import 'package:third_party.protobuf/test_messages_proto2.upb.dart'; import 'package:third_party.protobuf/test_messages_proto2.upb.dart';
import 'package:third_party.protobuf/test_messages_proto3.upb.dart'; import 'package:third_party.protobuf/test_messages_proto3.upb.dart';
@ -50,8 +49,8 @@ ConformanceResponse doTest(ConformanceRequest request) {
case ConformanceRequest_payload.protobufPayload: case ConformanceRequest_payload.protobufPayload:
try { try {
testMessage = isProto3 testMessage = isProto3
? TestAllTypesProto3.fromBinary(request.protobufPayload.data) ? TestAllTypesProto3.fromBinary(request.protobufPayload)
: TestAllTypesProto2.fromBinary(request.protobufPayload.data); : TestAllTypesProto2.fromBinary(request.protobufPayload);
} catch (e) { } catch (e) {
final parseErrorResponse = ConformanceResponse(); final parseErrorResponse = ConformanceResponse();
parseErrorResponse.parseError = '$e'; parseErrorResponse.parseError = '$e';
@ -66,8 +65,7 @@ ConformanceResponse doTest(ConformanceRequest request) {
switch (request.requestedOutputFormat) { switch (request.requestedOutputFormat) {
case WireFormat.PROTOBUF: case WireFormat.PROTOBUF:
try { try {
response.protobufPayload = response.protobufPayload = pb.GeneratedMessage.toBinary(testMessage);
Bytes(pb.GeneratedMessage.toBinary(testMessage));
} catch (e) { } catch (e) {
response.serializeError = '$e'; response.serializeError = '$e';
} }

@ -10,6 +10,8 @@
#import "Conformance.pbobjc.h" #import "Conformance.pbobjc.h"
#import "google/protobuf/TestMessagesProto2.pbobjc.h" #import "google/protobuf/TestMessagesProto2.pbobjc.h"
#import "google/protobuf/TestMessagesProto3.pbobjc.h" #import "google/protobuf/TestMessagesProto3.pbobjc.h"
#import "google/protobuf/editions/golden/TestMessagesProto2Editions.pbobjc.h"
#import "google/protobuf/editions/golden/TestMessagesProto3Editions.pbobjc.h"
static void Die(NSString *format, ...) __dead2; static void Die(NSString *format, ...) __dead2;
@ -49,22 +51,25 @@ static ConformanceResponse *DoTest(ConformanceRequest *request) {
break; break;
case ConformanceRequest_Payload_OneOfCase_ProtobufPayload: { case ConformanceRequest_Payload_OneOfCase_ProtobufPayload: {
Class msgClass = nil; NSDictionary *mappings = @{
if ([request.messageType isEqual:@"protobuf_test_messages.proto3.TestAllTypesProto3"]) { @"protobuf_test_messages.proto2.TestAllTypesProto2" : [Proto2TestAllTypesProto2 class],
msgClass = [Proto3TestAllTypesProto3 class]; @"protobuf_test_messages.proto3.TestAllTypesProto3" : [Proto3TestAllTypesProto3 class],
} else if ([request.messageType @"protobuf_test_messages.editions.proto2.TestAllTypesProto2" :
isEqual:@"protobuf_test_messages.proto2.TestAllTypesProto2"]) { [EditionsProto2TestAllTypesProto2 class],
msgClass = [Proto2TestAllTypesProto2 class]; @"protobuf_test_messages.editions.proto3.TestAllTypesProto3" :
[EditionsProto3TestAllTypesProto3 class],
};
Class msgClass = mappings[request.messageType];
if (msgClass) {
NSError *error = nil;
testMessage = [msgClass parseFromData:request.protobufPayload error:&error];
if (!testMessage) {
response.parseError = [NSString stringWithFormat:@"Parse error: %@", error];
}
} else { } else {
response.runtimeError = response.runtimeError =
[NSString stringWithFormat:@"Protobuf request had an unknown message_type: %@", [NSString stringWithFormat:@"Protobuf request had an unknown message_type: %@",
request.messageType]; request.messageType];
break;
}
NSError *error = nil;
testMessage = [msgClass parseFromData:request.protobufPayload error:&error];
if (!testMessage) {
response.parseError = [NSString stringWithFormat:@"Parse error: %@", error];
} }
break; break;
} }

@ -19,6 +19,8 @@ from google.protobuf import text_format
from google.protobuf import test_messages_proto2_pb2 from google.protobuf import test_messages_proto2_pb2
from google.protobuf import test_messages_proto3_pb2 from google.protobuf import test_messages_proto3_pb2
from conformance import conformance_pb2 from conformance import conformance_pb2
from google.protobuf.editions.golden import test_messages_proto2_editions_pb2
from google.protobuf.editions.golden import test_messages_proto3_editions_pb2
test_count = 0 test_count = 0
verbose = False verbose = False
@ -28,6 +30,18 @@ class ProtocolError(Exception):
pass pass
def _create_test_message(type):
if type == "protobuf_test_messages.proto2.TestAllTypesProto2":
return test_messages_proto2_pb2.TestAllTypesProto2()
if type == "protobuf_test_messages.proto3.TestAllTypesProto3":
return test_messages_proto3_pb2.TestAllTypesProto3()
if type == "protobuf_test_messages.editions.proto2.TestAllTypesProto2":
return test_messages_proto2_editions_pb2.TestAllTypesProto2()
if type == "protobuf_test_messages.editions.proto3.TestAllTypesProto3":
return test_messages_proto3_editions_pb2.TestAllTypesProto3()
return None
def do_test(request): def do_test(request):
response = conformance_pb2.ConformanceResponse() response = conformance_pb2.ConformanceResponse()
@ -85,16 +99,12 @@ def do_test(request):
response.protobuf_payload = failure_set.SerializeToString() response.protobuf_payload = failure_set.SerializeToString()
return response return response
isProto3 = (request.message_type == "protobuf_test_messages.proto3.TestAllTypesProto3")
isJson = (request.WhichOneof('payload') == 'json_payload') isJson = (request.WhichOneof('payload') == 'json_payload')
isProto2 = (request.message_type == "protobuf_test_messages.proto2.TestAllTypesProto2") test_message = _create_test_message(request.message_type)
if (not isProto3) and (not isJson) and (not isProto2): if (not isJson) and (test_message is None):
raise ProtocolError("Protobuf request doesn't have specific payload type") raise ProtocolError("Protobuf request doesn't have specific payload type")
test_message = test_messages_proto2_pb2.TestAllTypesProto2() if isProto2 else \
test_messages_proto3_pb2.TestAllTypesProto3()
try: try:
if request.WhichOneof('payload') == 'protobuf_payload': if request.WhichOneof('payload') == 'protobuf_payload':
try: try:

@ -24,7 +24,6 @@
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "conformance/conformance.pb.h" #include "conformance/conformance.pb.h"
#include "conformance/conformance.pb.h" #include "conformance/conformance.pb.h"
#include "google/protobuf/descriptor_legacy.h"
#include "google/protobuf/message.h" #include "google/protobuf/message.h"
#include "google/protobuf/text_format.h" #include "google/protobuf/text_format.h"
@ -143,13 +142,12 @@ ConformanceTestSuite::ConformanceRequestSetting::NewTestMessage() const {
std::string std::string
ConformanceTestSuite::ConformanceRequestSetting::GetSyntaxIdentifier() const { ConformanceTestSuite::ConformanceRequestSetting::GetSyntaxIdentifier() const {
switch (FileDescriptorLegacy(prototype_message_.GetDescriptor()->file()) switch (prototype_message_.GetDescriptor()->file()->edition()) {
.syntax()) { case Edition::EDITION_PROTO3:
case FileDescriptorLegacy::Syntax::SYNTAX_PROTO3:
return "Proto3"; return "Proto3";
case FileDescriptorLegacy::Syntax::SYNTAX_PROTO2: case Edition::EDITION_PROTO2:
return "Proto2"; return "Proto2";
case FileDescriptorLegacy::Syntax::SYNTAX_EDITIONS: { default: {
std::string id = "Editions"; std::string id = "Editions";
if (prototype_message_.GetDescriptor()->name() == "TestAllTypesProto2") { if (prototype_message_.GetDescriptor()->name() == "TestAllTypesProto2") {
absl::StrAppend(&id, "_Proto2"); absl::StrAppend(&id, "_Proto2");
@ -159,8 +157,6 @@ ConformanceTestSuite::ConformanceRequestSetting::GetSyntaxIdentifier() const {
} }
return id; return id;
} }
default:
return "Unknown";
} }
} }

@ -1,3 +1,6 @@
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInOptionalField.ProtobufOutput Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInOptionalField.ProtobufOutput
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput
Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInOptionalField.ProtobufOutput
Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput

@ -9,3 +9,6 @@
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInOptionalField.ProtobufOutput Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInOptionalField.ProtobufOutput
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput
Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInOptionalField.ProtobufOutput
Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput

@ -0,0 +1,6 @@
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInOptionalField.ProtobufOutput
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput
Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInOptionalField.ProtobufOutput
Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput

@ -7,3 +7,9 @@ Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput 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

@ -2,3 +2,7 @@ Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput 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

@ -0,0 +1,11 @@
# 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

@ -5,7 +5,7 @@
<title>Google Protocol Buffers tools</title> <title>Google Protocol Buffers tools</title>
<summary>Tools for Protocol Buffers - Google's data interchange format.</summary> <summary>Tools for Protocol Buffers - Google's data interchange format.</summary>
<description>See project site for more info.</description> <description>See project site for more info.</description>
<version>3.24.0</version> <version>3.25.0</version>
<authors>Google Inc.</authors> <authors>Google Inc.</authors>
<owners>protobuf-packages</owners> <owners>protobuf-packages</owners>
<licenseUrl>https://github.com/protocolbuffers/protobuf/blob/main/LICENSE</licenseUrl> <licenseUrl>https://github.com/protocolbuffers/protobuf/blob/main/LICENSE</licenseUrl>

@ -406,6 +406,12 @@ namespace Google.Protobuf
Merge(new FieldMaskTree().AddFieldPath("payload.single_int32"), Merge(new FieldMaskTree().AddFieldPath("payload.single_int32"),
sourceWithPayloadInt32Unset, destination, options, useDynamicMessage); sourceWithPayloadInt32Unset, destination, options, useDynamicMessage);
Assert.IsNotNull(destination.Payload); Assert.IsNotNull(destination.Payload);
// Clear unset primitive fields even if source payload is cleared
destination = source.Clone();
Merge(new FieldMaskTree().AddFieldPath("payload.single_int32"),
clearedSource, destination, options, useDynamicMessage);
Assert.AreEqual(0, destination.Payload.SingleInt32);
} }
[Test] [Test]

@ -33,24 +33,25 @@ namespace Google.Protobuf.Compiler {
"LnByb3RvYnVmLkZpbGVEZXNjcmlwdG9yUHJvdG8SRQoXc291cmNlX2ZpbGVf", "LnByb3RvYnVmLkZpbGVEZXNjcmlwdG9yUHJvdG8SRQoXc291cmNlX2ZpbGVf",
"ZGVzY3JpcHRvcnMYESADKAsyJC5nb29nbGUucHJvdG9idWYuRmlsZURlc2Ny", "ZGVzY3JpcHRvcnMYESADKAsyJC5nb29nbGUucHJvdG9idWYuRmlsZURlc2Ny",
"aXB0b3JQcm90bxI7ChBjb21waWxlcl92ZXJzaW9uGAMgASgLMiEuZ29vZ2xl", "aXB0b3JQcm90bxI7ChBjb21waWxlcl92ZXJzaW9uGAMgASgLMiEuZ29vZ2xl",
"LnByb3RvYnVmLmNvbXBpbGVyLlZlcnNpb24i4AIKFUNvZGVHZW5lcmF0b3JS", "LnByb3RvYnVmLmNvbXBpbGVyLlZlcnNpb24ikgMKFUNvZGVHZW5lcmF0b3JS",
"ZXNwb25zZRINCgVlcnJvchgBIAEoCRIaChJzdXBwb3J0ZWRfZmVhdHVyZXMY", "ZXNwb25zZRINCgVlcnJvchgBIAEoCRIaChJzdXBwb3J0ZWRfZmVhdHVyZXMY",
"AiABKAQSQgoEZmlsZRgPIAMoCzI0Lmdvb2dsZS5wcm90b2J1Zi5jb21waWxl", "AiABKAQSFwoPbWluaW11bV9lZGl0aW9uGAMgASgFEhcKD21heGltdW1fZWRp",
"ci5Db2RlR2VuZXJhdG9yUmVzcG9uc2UuRmlsZRp/CgRGaWxlEgwKBG5hbWUY", "dGlvbhgEIAEoBRJCCgRmaWxlGA8gAygLMjQuZ29vZ2xlLnByb3RvYnVmLmNv",
"ASABKAkSFwoPaW5zZXJ0aW9uX3BvaW50GAIgASgJEg8KB2NvbnRlbnQYDyAB", "bXBpbGVyLkNvZGVHZW5lcmF0b3JSZXNwb25zZS5GaWxlGn8KBEZpbGUSDAoE",
"KAkSPwoTZ2VuZXJhdGVkX2NvZGVfaW5mbxgQIAEoCzIiLmdvb2dsZS5wcm90", "bmFtZRgBIAEoCRIXCg9pbnNlcnRpb25fcG9pbnQYAiABKAkSDwoHY29udGVu",
"b2J1Zi5HZW5lcmF0ZWRDb2RlSW5mbyJXCgdGZWF0dXJlEhAKDEZFQVRVUkVf", "dBgPIAEoCRI/ChNnZW5lcmF0ZWRfY29kZV9pbmZvGBAgASgLMiIuZ29vZ2xl",
"Tk9ORRAAEhsKF0ZFQVRVUkVfUFJPVE8zX09QVElPTkFMEAESHQoZRkVBVFVS", "LnByb3RvYnVmLkdlbmVyYXRlZENvZGVJbmZvIlcKB0ZlYXR1cmUSEAoMRkVB",
"RV9TVVBQT1JUU19FRElUSU9OUxACQnIKHGNvbS5nb29nbGUucHJvdG9idWYu", "VFVSRV9OT05FEAASGwoXRkVBVFVSRV9QUk9UTzNfT1BUSU9OQUwQARIdChlG",
"Y29tcGlsZXJCDFBsdWdpblByb3Rvc1opZ29vZ2xlLmdvbGFuZy5vcmcvcHJv", "RUFUVVJFX1NVUFBPUlRTX0VESVRJT05TEAJCcgocY29tLmdvb2dsZS5wcm90",
"dG9idWYvdHlwZXMvcGx1Z2lucGKqAhhHb29nbGUuUHJvdG9idWYuQ29tcGls", "b2J1Zi5jb21waWxlckIMUGx1Z2luUHJvdG9zWilnb29nbGUuZ29sYW5nLm9y",
"ZXI=")); "Zy9wcm90b2J1Zi90eXBlcy9wbHVnaW5wYqoCGEdvb2dsZS5Qcm90b2J1Zi5D",
"b21waWxlcg=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor, }, new pbr::FileDescriptor[] { global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor, },
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Compiler.Version), global::Google.Protobuf.Compiler.Version.Parser, new[]{ "Major", "Minor", "Patch", "Suffix" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Compiler.Version), global::Google.Protobuf.Compiler.Version.Parser, new[]{ "Major", "Minor", "Patch", "Suffix" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Compiler.CodeGeneratorRequest), global::Google.Protobuf.Compiler.CodeGeneratorRequest.Parser, new[]{ "FileToGenerate", "Parameter", "ProtoFile", "SourceFileDescriptors", "CompilerVersion" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Compiler.CodeGeneratorRequest), global::Google.Protobuf.Compiler.CodeGeneratorRequest.Parser, new[]{ "FileToGenerate", "Parameter", "ProtoFile", "SourceFileDescriptors", "CompilerVersion" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Compiler.CodeGeneratorResponse), global::Google.Protobuf.Compiler.CodeGeneratorResponse.Parser, new[]{ "Error", "SupportedFeatures", "File" }, null, new[]{ typeof(global::Google.Protobuf.Compiler.CodeGeneratorResponse.Types.Feature) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Compiler.CodeGeneratorResponse.Types.File), global::Google.Protobuf.Compiler.CodeGeneratorResponse.Types.File.Parser, new[]{ "Name", "InsertionPoint", "Content", "GeneratedCodeInfo" }, null, null, null, null)}) new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Compiler.CodeGeneratorResponse), global::Google.Protobuf.Compiler.CodeGeneratorResponse.Parser, new[]{ "Error", "SupportedFeatures", "MinimumEdition", "MaximumEdition", "File" }, null, new[]{ typeof(global::Google.Protobuf.Compiler.CodeGeneratorResponse.Types.Feature) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Compiler.CodeGeneratorResponse.Types.File), global::Google.Protobuf.Compiler.CodeGeneratorResponse.Types.File.Parser, new[]{ "Name", "InsertionPoint", "Content", "GeneratedCodeInfo" }, null, null, null, null)})
})); }));
} }
#endregion #endregion
@ -836,6 +837,8 @@ namespace Google.Protobuf.Compiler {
_hasBits0 = other._hasBits0; _hasBits0 = other._hasBits0;
error_ = other.error_; error_ = other.error_;
supportedFeatures_ = other.supportedFeatures_; supportedFeatures_ = other.supportedFeatures_;
minimumEdition_ = other.minimumEdition_;
maximumEdition_ = other.maximumEdition_;
file_ = other.file_.Clone(); file_ = other.file_.Clone();
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
} }
@ -913,6 +916,72 @@ namespace Google.Protobuf.Compiler {
_hasBits0 &= ~1; _hasBits0 &= ~1;
} }
/// <summary>Field number for the "minimum_edition" field.</summary>
public const int MinimumEditionFieldNumber = 3;
private readonly static int MinimumEditionDefaultValue = 0;
private int minimumEdition_;
/// <summary>
/// The minimum edition this plugin supports. This will be treated as an
/// Edition enum, but we want to allow unknown values. It should be specified
/// according the edition enum value, *not* the edition number. Only takes
/// effect for plugins that have FEATURE_SUPPORTS_EDITIONS set.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int MinimumEdition {
get { if ((_hasBits0 & 2) != 0) { return minimumEdition_; } else { return MinimumEditionDefaultValue; } }
set {
_hasBits0 |= 2;
minimumEdition_ = value;
}
}
/// <summary>Gets whether the "minimum_edition" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool HasMinimumEdition {
get { return (_hasBits0 & 2) != 0; }
}
/// <summary>Clears the value of the "minimum_edition" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void ClearMinimumEdition() {
_hasBits0 &= ~2;
}
/// <summary>Field number for the "maximum_edition" field.</summary>
public const int MaximumEditionFieldNumber = 4;
private readonly static int MaximumEditionDefaultValue = 0;
private int maximumEdition_;
/// <summary>
/// The maximum edition this plugin supports. This will be treated as an
/// Edition enum, but we want to allow unknown values. It should be specified
/// according the edition enum value, *not* the edition number. Only takes
/// effect for plugins that have FEATURE_SUPPORTS_EDITIONS set.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int MaximumEdition {
get { if ((_hasBits0 & 4) != 0) { return maximumEdition_; } else { return MaximumEditionDefaultValue; } }
set {
_hasBits0 |= 4;
maximumEdition_ = value;
}
}
/// <summary>Gets whether the "maximum_edition" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool HasMaximumEdition {
get { return (_hasBits0 & 4) != 0; }
}
/// <summary>Clears the value of the "maximum_edition" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void ClearMaximumEdition() {
_hasBits0 &= ~4;
}
/// <summary>Field number for the "file" field.</summary> /// <summary>Field number for the "file" field.</summary>
public const int FileFieldNumber = 15; public const int FileFieldNumber = 15;
private static readonly pb::FieldCodec<global::Google.Protobuf.Compiler.CodeGeneratorResponse.Types.File> _repeated_file_codec private static readonly pb::FieldCodec<global::Google.Protobuf.Compiler.CodeGeneratorResponse.Types.File> _repeated_file_codec
@ -941,6 +1010,8 @@ namespace Google.Protobuf.Compiler {
} }
if (Error != other.Error) return false; if (Error != other.Error) return false;
if (SupportedFeatures != other.SupportedFeatures) return false; if (SupportedFeatures != other.SupportedFeatures) return false;
if (MinimumEdition != other.MinimumEdition) return false;
if (MaximumEdition != other.MaximumEdition) return false;
if(!file_.Equals(other.file_)) return false; if(!file_.Equals(other.file_)) return false;
return Equals(_unknownFields, other._unknownFields); return Equals(_unknownFields, other._unknownFields);
} }
@ -951,6 +1022,8 @@ namespace Google.Protobuf.Compiler {
int hash = 1; int hash = 1;
if (HasError) hash ^= Error.GetHashCode(); if (HasError) hash ^= Error.GetHashCode();
if (HasSupportedFeatures) hash ^= SupportedFeatures.GetHashCode(); if (HasSupportedFeatures) hash ^= SupportedFeatures.GetHashCode();
if (HasMinimumEdition) hash ^= MinimumEdition.GetHashCode();
if (HasMaximumEdition) hash ^= MaximumEdition.GetHashCode();
hash ^= file_.GetHashCode(); hash ^= file_.GetHashCode();
if (_unknownFields != null) { if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode(); hash ^= _unknownFields.GetHashCode();
@ -978,6 +1051,14 @@ namespace Google.Protobuf.Compiler {
output.WriteRawTag(16); output.WriteRawTag(16);
output.WriteUInt64(SupportedFeatures); output.WriteUInt64(SupportedFeatures);
} }
if (HasMinimumEdition) {
output.WriteRawTag(24);
output.WriteInt32(MinimumEdition);
}
if (HasMaximumEdition) {
output.WriteRawTag(32);
output.WriteInt32(MaximumEdition);
}
file_.WriteTo(output, _repeated_file_codec); file_.WriteTo(output, _repeated_file_codec);
if (_unknownFields != null) { if (_unknownFields != null) {
_unknownFields.WriteTo(output); _unknownFields.WriteTo(output);
@ -997,6 +1078,14 @@ namespace Google.Protobuf.Compiler {
output.WriteRawTag(16); output.WriteRawTag(16);
output.WriteUInt64(SupportedFeatures); output.WriteUInt64(SupportedFeatures);
} }
if (HasMinimumEdition) {
output.WriteRawTag(24);
output.WriteInt32(MinimumEdition);
}
if (HasMaximumEdition) {
output.WriteRawTag(32);
output.WriteInt32(MaximumEdition);
}
file_.WriteTo(ref output, _repeated_file_codec); file_.WriteTo(ref output, _repeated_file_codec);
if (_unknownFields != null) { if (_unknownFields != null) {
_unknownFields.WriteTo(ref output); _unknownFields.WriteTo(ref output);
@ -1014,6 +1103,12 @@ namespace Google.Protobuf.Compiler {
if (HasSupportedFeatures) { if (HasSupportedFeatures) {
size += 1 + pb::CodedOutputStream.ComputeUInt64Size(SupportedFeatures); size += 1 + pb::CodedOutputStream.ComputeUInt64Size(SupportedFeatures);
} }
if (HasMinimumEdition) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(MinimumEdition);
}
if (HasMaximumEdition) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(MaximumEdition);
}
size += file_.CalculateSize(_repeated_file_codec); size += file_.CalculateSize(_repeated_file_codec);
if (_unknownFields != null) { if (_unknownFields != null) {
size += _unknownFields.CalculateSize(); size += _unknownFields.CalculateSize();
@ -1033,6 +1128,12 @@ namespace Google.Protobuf.Compiler {
if (other.HasSupportedFeatures) { if (other.HasSupportedFeatures) {
SupportedFeatures = other.SupportedFeatures; SupportedFeatures = other.SupportedFeatures;
} }
if (other.HasMinimumEdition) {
MinimumEdition = other.MinimumEdition;
}
if (other.HasMaximumEdition) {
MaximumEdition = other.MaximumEdition;
}
file_.Add(other.file_); file_.Add(other.file_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
} }
@ -1057,6 +1158,14 @@ namespace Google.Protobuf.Compiler {
SupportedFeatures = input.ReadUInt64(); SupportedFeatures = input.ReadUInt64();
break; break;
} }
case 24: {
MinimumEdition = input.ReadInt32();
break;
}
case 32: {
MaximumEdition = input.ReadInt32();
break;
}
case 122: { case 122: {
file_.AddEntriesFrom(input, _repeated_file_codec); file_.AddEntriesFrom(input, _repeated_file_codec);
break; break;
@ -1084,6 +1193,14 @@ namespace Google.Protobuf.Compiler {
SupportedFeatures = input.ReadUInt64(); SupportedFeatures = input.ReadUInt64();
break; break;
} }
case 24: {
MinimumEdition = input.ReadInt32();
break;
}
case 32: {
MaximumEdition = input.ReadInt32();
break;
}
case 122: { case 122: {
file_.AddEntriesFrom(ref input, _repeated_file_codec); file_.AddEntriesFrom(ref input, _repeated_file_codec);
break; break;

@ -270,6 +270,13 @@ namespace Google.Protobuf
field.Accessor.SetValue(destination, destinationField); field.Accessor.SetValue(destination, destinationField);
} }
if (sourceField == null)
{
// If the message field is not present in the source but is in the destination, create an empty one
// so we can properly handle child entries
sourceField = field.MessageType.Parser.CreateTemplate();
}
var childPath = path.Length == 0 ? entry.Key : path + "." + entry.Key; var childPath = path.Length == 0 ? entry.Key : path + "." + entry.Key;
Merge(entry.Value, childPath, (IMessage)sourceField, (IMessage)destinationField, options); Merge(entry.Value, childPath, (IMessage)sourceField, (IMessage)destinationField, options);
continue; continue;

@ -5,7 +5,7 @@
<Description>C# runtime library for Protocol Buffers - Google's data interchange format.</Description> <Description>C# runtime library for Protocol Buffers - Google's data interchange format.</Description>
<Copyright>Copyright 2015, Google Inc.</Copyright> <Copyright>Copyright 2015, Google Inc.</Copyright>
<AssemblyTitle>Google Protocol Buffers</AssemblyTitle> <AssemblyTitle>Google Protocol Buffers</AssemblyTitle>
<VersionPrefix>3.24.0</VersionPrefix> <VersionPrefix>3.25.0</VersionPrefix>
<LangVersion>10.0</LangVersion> <LangVersion>10.0</LangVersion>
<Authors>Google Inc.</Authors> <Authors>Google Inc.</Authors>
<TargetFrameworks>netstandard1.1;netstandard2.0;net45;net50</TargetFrameworks> <TargetFrameworks>netstandard1.1;netstandard2.0;net45;net50</TargetFrameworks>

@ -53,190 +53,190 @@ namespace Google.Protobuf.Reflection {
"X25hbWUYCiADKAkaZQoORXh0ZW5zaW9uUmFuZ2USDQoFc3RhcnQYASABKAUS", "X25hbWUYCiADKAkaZQoORXh0ZW5zaW9uUmFuZ2USDQoFc3RhcnQYASABKAUS",
"CwoDZW5kGAIgASgFEjcKB29wdGlvbnMYAyABKAsyJi5nb29nbGUucHJvdG9i", "CwoDZW5kGAIgASgFEjcKB29wdGlvbnMYAyABKAsyJi5nb29nbGUucHJvdG9i",
"dWYuRXh0ZW5zaW9uUmFuZ2VPcHRpb25zGisKDVJlc2VydmVkUmFuZ2USDQoF", "dWYuRXh0ZW5zaW9uUmFuZ2VPcHRpb25zGisKDVJlc2VydmVkUmFuZ2USDQoF",
"c3RhcnQYASABKAUSCwoDZW5kGAIgASgFIuADChVFeHRlbnNpb25SYW5nZU9w", "c3RhcnQYASABKAUSCwoDZW5kGAIgASgFIuUDChVFeHRlbnNpb25SYW5nZU9w",
"dGlvbnMSQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xl", "dGlvbnMSQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xl",
"LnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24STAoLZGVjbGFyYXRpb24Y", "LnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24STAoLZGVjbGFyYXRpb24Y",
"AiADKAsyMi5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmFuZ2VPcHRpb25z", "AiADKAsyMi5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmFuZ2VPcHRpb25z",
"LkRlY2xhcmF0aW9uQgOIAQISLQoIZmVhdHVyZXMYMiABKAsyGy5nb29nbGUu", "LkRlY2xhcmF0aW9uQgOIAQISLQoIZmVhdHVyZXMYMiABKAsyGy5nb29nbGUu",
"cHJvdG9idWYuRmVhdHVyZVNldBJaCgx2ZXJpZmljYXRpb24YAyABKA4yOC5n", "cHJvdG9idWYuRmVhdHVyZVNldBJfCgx2ZXJpZmljYXRpb24YAyABKA4yOC5n",
"b29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmFuZ2VPcHRpb25zLlZlcmlmaWNh", "b29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmFuZ2VPcHRpb25zLlZlcmlmaWNh",
"dGlvblN0YXRlOgpVTlZFUklGSUVEGmgKC0RlY2xhcmF0aW9uEg4KBm51bWJl", "dGlvblN0YXRlOgpVTlZFUklGSUVEQgOIAQIaaAoLRGVjbGFyYXRpb24SDgoG",
"chgBIAEoBRIRCglmdWxsX25hbWUYAiABKAkSDAoEdHlwZRgDIAEoCRIQCghy", "bnVtYmVyGAEgASgFEhEKCWZ1bGxfbmFtZRgCIAEoCRIMCgR0eXBlGAMgASgJ",
"ZXNlcnZlZBgFIAEoCBIQCghyZXBlYXRlZBgGIAEoCEoECAQQBSI0ChFWZXJp", "EhAKCHJlc2VydmVkGAUgASgIEhAKCHJlcGVhdGVkGAYgASgISgQIBBAFIjQK",
"ZmljYXRpb25TdGF0ZRIPCgtERUNMQVJBVElPThAAEg4KClVOVkVSSUZJRUQQ", "EVZlcmlmaWNhdGlvblN0YXRlEg8KC0RFQ0xBUkFUSU9OEAASDgoKVU5WRVJJ",
"ASoJCOgHEICAgIACItUFChRGaWVsZERlc2NyaXB0b3JQcm90bxIMCgRuYW1l", "RklFRBABKgkI6AcQgICAgAIi1QUKFEZpZWxkRGVzY3JpcHRvclByb3RvEgwK",
"GAEgASgJEg4KBm51bWJlchgDIAEoBRI6CgVsYWJlbBgEIAEoDjIrLmdvb2ds", "BG5hbWUYASABKAkSDgoGbnVtYmVyGAMgASgFEjoKBWxhYmVsGAQgASgOMisu",
"ZS5wcm90b2J1Zi5GaWVsZERlc2NyaXB0b3JQcm90by5MYWJlbBI4CgR0eXBl", "Z29vZ2xlLnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvLkxhYmVsEjgK",
"GAUgASgOMiouZ29vZ2xlLnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3Rv", "BHR5cGUYBSABKA4yKi5nb29nbGUucHJvdG9idWYuRmllbGREZXNjcmlwdG9y",
"LlR5cGUSEQoJdHlwZV9uYW1lGAYgASgJEhAKCGV4dGVuZGVlGAIgASgJEhUK", "UHJvdG8uVHlwZRIRCgl0eXBlX25hbWUYBiABKAkSEAoIZXh0ZW5kZWUYAiAB",
"DWRlZmF1bHRfdmFsdWUYByABKAkSEwoLb25lb2ZfaW5kZXgYCSABKAUSEQoJ", "KAkSFQoNZGVmYXVsdF92YWx1ZRgHIAEoCRITCgtvbmVvZl9pbmRleBgJIAEo",
"anNvbl9uYW1lGAogASgJEi4KB29wdGlvbnMYCCABKAsyHS5nb29nbGUucHJv", "BRIRCglqc29uX25hbWUYCiABKAkSLgoHb3B0aW9ucxgIIAEoCzIdLmdvb2ds",
"dG9idWYuRmllbGRPcHRpb25zEhcKD3Byb3RvM19vcHRpb25hbBgRIAEoCCK2", "ZS5wcm90b2J1Zi5GaWVsZE9wdGlvbnMSFwoPcHJvdG8zX29wdGlvbmFsGBEg",
"AgoEVHlwZRIPCgtUWVBFX0RPVUJMRRABEg4KClRZUEVfRkxPQVQQAhIOCgpU", "ASgIIrYCCgRUeXBlEg8KC1RZUEVfRE9VQkxFEAESDgoKVFlQRV9GTE9BVBAC",
"WVBFX0lOVDY0EAMSDwoLVFlQRV9VSU5UNjQQBBIOCgpUWVBFX0lOVDMyEAUS", "Eg4KClRZUEVfSU5UNjQQAxIPCgtUWVBFX1VJTlQ2NBAEEg4KClRZUEVfSU5U",
"EAoMVFlQRV9GSVhFRDY0EAYSEAoMVFlQRV9GSVhFRDMyEAcSDQoJVFlQRV9C", "MzIQBRIQCgxUWVBFX0ZJWEVENjQQBhIQCgxUWVBFX0ZJWEVEMzIQBxINCglU",
"T09MEAgSDwoLVFlQRV9TVFJJTkcQCRIOCgpUWVBFX0dST1VQEAoSEAoMVFlQ", "WVBFX0JPT0wQCBIPCgtUWVBFX1NUUklORxAJEg4KClRZUEVfR1JPVVAQChIQ",
"RV9NRVNTQUdFEAsSDgoKVFlQRV9CWVRFUxAMEg8KC1RZUEVfVUlOVDMyEA0S", "CgxUWVBFX01FU1NBR0UQCxIOCgpUWVBFX0JZVEVTEAwSDwoLVFlQRV9VSU5U",
"DQoJVFlQRV9FTlVNEA4SEQoNVFlQRV9TRklYRUQzMhAPEhEKDVRZUEVfU0ZJ", "MzIQDRINCglUWVBFX0VOVU0QDhIRCg1UWVBFX1NGSVhFRDMyEA8SEQoNVFlQ",
"WEVENjQQEBIPCgtUWVBFX1NJTlQzMhAREg8KC1RZUEVfU0lOVDY0EBIiQwoF", "RV9TRklYRUQ2NBAQEg8KC1RZUEVfU0lOVDMyEBESDwoLVFlQRV9TSU5UNjQQ",
"TGFiZWwSEgoOTEFCRUxfT1BUSU9OQUwQARISCg5MQUJFTF9SRVBFQVRFRBAD", "EiJDCgVMYWJlbBISCg5MQUJFTF9PUFRJT05BTBABEhIKDkxBQkVMX1JFUEVB",
"EhIKDkxBQkVMX1JFUVVJUkVEEAIiVAoUT25lb2ZEZXNjcmlwdG9yUHJvdG8S", "VEVEEAMSEgoOTEFCRUxfUkVRVUlSRUQQAiJUChRPbmVvZkRlc2NyaXB0b3JQ",
"DAoEbmFtZRgBIAEoCRIuCgdvcHRpb25zGAIgASgLMh0uZ29vZ2xlLnByb3Rv", "cm90bxIMCgRuYW1lGAEgASgJEi4KB29wdGlvbnMYAiABKAsyHS5nb29nbGUu",
"YnVmLk9uZW9mT3B0aW9ucyKkAgoTRW51bURlc2NyaXB0b3JQcm90bxIMCgRu", "cHJvdG9idWYuT25lb2ZPcHRpb25zIqQCChNFbnVtRGVzY3JpcHRvclByb3Rv",
"YW1lGAEgASgJEjgKBXZhbHVlGAIgAygLMikuZ29vZ2xlLnByb3RvYnVmLkVu", "EgwKBG5hbWUYASABKAkSOAoFdmFsdWUYAiADKAsyKS5nb29nbGUucHJvdG9i",
"dW1WYWx1ZURlc2NyaXB0b3JQcm90bxItCgdvcHRpb25zGAMgASgLMhwuZ29v", "dWYuRW51bVZhbHVlRGVzY3JpcHRvclByb3RvEi0KB29wdGlvbnMYAyABKAsy",
"Z2xlLnByb3RvYnVmLkVudW1PcHRpb25zEk4KDnJlc2VydmVkX3JhbmdlGAQg", "HC5nb29nbGUucHJvdG9idWYuRW51bU9wdGlvbnMSTgoOcmVzZXJ2ZWRfcmFu",
"AygLMjYuZ29vZ2xlLnByb3RvYnVmLkVudW1EZXNjcmlwdG9yUHJvdG8uRW51", "Z2UYBCADKAsyNi5nb29nbGUucHJvdG9idWYuRW51bURlc2NyaXB0b3JQcm90",
"bVJlc2VydmVkUmFuZ2USFQoNcmVzZXJ2ZWRfbmFtZRgFIAMoCRovChFFbnVt", "by5FbnVtUmVzZXJ2ZWRSYW5nZRIVCg1yZXNlcnZlZF9uYW1lGAUgAygJGi8K",
"UmVzZXJ2ZWRSYW5nZRINCgVzdGFydBgBIAEoBRILCgNlbmQYAiABKAUibAoY", "EUVudW1SZXNlcnZlZFJhbmdlEg0KBXN0YXJ0GAEgASgFEgsKA2VuZBgCIAEo",
"RW51bVZhbHVlRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSDgoGbnVt", "BSJsChhFbnVtVmFsdWVEZXNjcmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRIO",
"YmVyGAIgASgFEjIKB29wdGlvbnMYAyABKAsyIS5nb29nbGUucHJvdG9idWYu", "CgZudW1iZXIYAiABKAUSMgoHb3B0aW9ucxgDIAEoCzIhLmdvb2dsZS5wcm90",
"RW51bVZhbHVlT3B0aW9ucyKQAQoWU2VydmljZURlc2NyaXB0b3JQcm90bxIM", "b2J1Zi5FbnVtVmFsdWVPcHRpb25zIpABChZTZXJ2aWNlRGVzY3JpcHRvclBy",
"CgRuYW1lGAEgASgJEjYKBm1ldGhvZBgCIAMoCzImLmdvb2dsZS5wcm90b2J1", "b3RvEgwKBG5hbWUYASABKAkSNgoGbWV0aG9kGAIgAygLMiYuZ29vZ2xlLnBy",
"Zi5NZXRob2REZXNjcmlwdG9yUHJvdG8SMAoHb3B0aW9ucxgDIAEoCzIfLmdv", "b3RvYnVmLk1ldGhvZERlc2NyaXB0b3JQcm90bxIwCgdvcHRpb25zGAMgASgL",
"b2dsZS5wcm90b2J1Zi5TZXJ2aWNlT3B0aW9ucyLBAQoVTWV0aG9kRGVzY3Jp", "Mh8uZ29vZ2xlLnByb3RvYnVmLlNlcnZpY2VPcHRpb25zIsEBChVNZXRob2RE",
"cHRvclByb3RvEgwKBG5hbWUYASABKAkSEgoKaW5wdXRfdHlwZRgCIAEoCRIT", "ZXNjcmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRISCgppbnB1dF90eXBlGAIg",
"CgtvdXRwdXRfdHlwZRgDIAEoCRIvCgdvcHRpb25zGAQgASgLMh4uZ29vZ2xl", "ASgJEhMKC291dHB1dF90eXBlGAMgASgJEi8KB29wdGlvbnMYBCABKAsyHi5n",
"LnByb3RvYnVmLk1ldGhvZE9wdGlvbnMSHwoQY2xpZW50X3N0cmVhbWluZxgF", "b29nbGUucHJvdG9idWYuTWV0aG9kT3B0aW9ucxIfChBjbGllbnRfc3RyZWFt",
"IAEoCDoFZmFsc2USHwoQc2VydmVyX3N0cmVhbWluZxgGIAEoCDoFZmFsc2Ui", "aW5nGAUgASgIOgVmYWxzZRIfChBzZXJ2ZXJfc3RyZWFtaW5nGAYgASgIOgVm",
"1AYKC0ZpbGVPcHRpb25zEhQKDGphdmFfcGFja2FnZRgBIAEoCRIcChRqYXZh", "YWxzZSLUBgoLRmlsZU9wdGlvbnMSFAoMamF2YV9wYWNrYWdlGAEgASgJEhwK",
"X291dGVyX2NsYXNzbmFtZRgIIAEoCRIiChNqYXZhX211bHRpcGxlX2ZpbGVz", "FGphdmFfb3V0ZXJfY2xhc3NuYW1lGAggASgJEiIKE2phdmFfbXVsdGlwbGVf",
"GAogASgIOgVmYWxzZRIpCh1qYXZhX2dlbmVyYXRlX2VxdWFsc19hbmRfaGFz", "ZmlsZXMYCiABKAg6BWZhbHNlEikKHWphdmFfZ2VuZXJhdGVfZXF1YWxzX2Fu",
"aBgUIAEoCEICGAESJQoWamF2YV9zdHJpbmdfY2hlY2tfdXRmOBgbIAEoCDoF", "ZF9oYXNoGBQgASgIQgIYARIlChZqYXZhX3N0cmluZ19jaGVja191dGY4GBsg",
"ZmFsc2USRgoMb3B0aW1pemVfZm9yGAkgASgOMikuZ29vZ2xlLnByb3RvYnVm", "ASgIOgVmYWxzZRJGCgxvcHRpbWl6ZV9mb3IYCSABKA4yKS5nb29nbGUucHJv",
"LkZpbGVPcHRpb25zLk9wdGltaXplTW9kZToFU1BFRUQSEgoKZ29fcGFja2Fn", "dG9idWYuRmlsZU9wdGlvbnMuT3B0aW1pemVNb2RlOgVTUEVFRBISCgpnb19w",
"ZRgLIAEoCRIiChNjY19nZW5lcmljX3NlcnZpY2VzGBAgASgIOgVmYWxzZRIk", "YWNrYWdlGAsgASgJEiIKE2NjX2dlbmVyaWNfc2VydmljZXMYECABKAg6BWZh",
"ChVqYXZhX2dlbmVyaWNfc2VydmljZXMYESABKAg6BWZhbHNlEiIKE3B5X2dl", "bHNlEiQKFWphdmFfZ2VuZXJpY19zZXJ2aWNlcxgRIAEoCDoFZmFsc2USIgoT",
"bmVyaWNfc2VydmljZXMYEiABKAg6BWZhbHNlEiMKFHBocF9nZW5lcmljX3Nl", "cHlfZ2VuZXJpY19zZXJ2aWNlcxgSIAEoCDoFZmFsc2USIwoUcGhwX2dlbmVy",
"cnZpY2VzGCogASgIOgVmYWxzZRIZCgpkZXByZWNhdGVkGBcgASgIOgVmYWxz", "aWNfc2VydmljZXMYKiABKAg6BWZhbHNlEhkKCmRlcHJlY2F0ZWQYFyABKAg6",
"ZRIeChBjY19lbmFibGVfYXJlbmFzGB8gASgIOgR0cnVlEhkKEW9iamNfY2xh", "BWZhbHNlEh4KEGNjX2VuYWJsZV9hcmVuYXMYHyABKAg6BHRydWUSGQoRb2Jq",
"c3NfcHJlZml4GCQgASgJEhgKEGNzaGFycF9uYW1lc3BhY2UYJSABKAkSFAoM", "Y19jbGFzc19wcmVmaXgYJCABKAkSGAoQY3NoYXJwX25hbWVzcGFjZRglIAEo",
"c3dpZnRfcHJlZml4GCcgASgJEhgKEHBocF9jbGFzc19wcmVmaXgYKCABKAkS", "CRIUCgxzd2lmdF9wcmVmaXgYJyABKAkSGAoQcGhwX2NsYXNzX3ByZWZpeBgo",
"FQoNcGhwX25hbWVzcGFjZRgpIAEoCRIeChZwaHBfbWV0YWRhdGFfbmFtZXNw", "IAEoCRIVCg1waHBfbmFtZXNwYWNlGCkgASgJEh4KFnBocF9tZXRhZGF0YV9u",
"YWNlGCwgASgJEhQKDHJ1YnlfcGFja2FnZRgtIAEoCRItCghmZWF0dXJlcxgy", "YW1lc3BhY2UYLCABKAkSFAoMcnVieV9wYWNrYWdlGC0gASgJEi0KCGZlYXR1",
"IAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJlU2V0EkMKFHVuaW50ZXJw", "cmVzGDIgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkZlYXR1cmVTZXQSQwoUdW5p",
"cmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVy", "bnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVu",
"cHJldGVkT3B0aW9uIjoKDE9wdGltaXplTW9kZRIJCgVTUEVFRBABEg0KCUNP", "aW50ZXJwcmV0ZWRPcHRpb24iOgoMT3B0aW1pemVNb2RlEgkKBVNQRUVEEAES",
"REVfU0laRRACEhAKDExJVEVfUlVOVElNRRADKgkI6AcQgICAgAJKBAgmECci", "DQoJQ09ERV9TSVpFEAISEAoMTElURV9SVU5USU1FEAMqCQjoBxCAgICAAkoE",
"5wIKDk1lc3NhZ2VPcHRpb25zEiYKF21lc3NhZ2Vfc2V0X3dpcmVfZm9ybWF0", "CCYQJyLnAgoOTWVzc2FnZU9wdGlvbnMSJgoXbWVzc2FnZV9zZXRfd2lyZV9m",
"GAEgASgIOgVmYWxzZRIuCh9ub19zdGFuZGFyZF9kZXNjcmlwdG9yX2FjY2Vz", "b3JtYXQYASABKAg6BWZhbHNlEi4KH25vX3N0YW5kYXJkX2Rlc2NyaXB0b3Jf",
"c29yGAIgASgIOgVmYWxzZRIZCgpkZXByZWNhdGVkGAMgASgIOgVmYWxzZRIR", "YWNjZXNzb3IYAiABKAg6BWZhbHNlEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZh",
"CgltYXBfZW50cnkYByABKAgSMgomZGVwcmVjYXRlZF9sZWdhY3lfanNvbl9m", "bHNlEhEKCW1hcF9lbnRyeRgHIAEoCBIyCiZkZXByZWNhdGVkX2xlZ2FjeV9q",
"aWVsZF9jb25mbGljdHMYCyABKAhCAhgBEi0KCGZlYXR1cmVzGAwgASgLMhsu", "c29uX2ZpZWxkX2NvbmZsaWN0cxgLIAEoCEICGAESLQoIZmVhdHVyZXMYDCAB",
"Z29vZ2xlLnByb3RvYnVmLkZlYXR1cmVTZXQSQwoUdW5pbnRlcnByZXRlZF9v", "KAsyGy5nb29nbGUucHJvdG9idWYuRmVhdHVyZVNldBJDChR1bmludGVycHJl",
"dGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnBy",
"ZXRlZE9wdGlvbioJCOgHEICAgIACSgQIBBAFSgQIBRAGSgQIBhAHSgQICBAJ",
"SgQICRAKIo0JCgxGaWVsZE9wdGlvbnMSOgoFY3R5cGUYASABKA4yIy5nb29n",
"bGUucHJvdG9idWYuRmllbGRPcHRpb25zLkNUeXBlOgZTVFJJTkcSDgoGcGFj",
"a2VkGAIgASgIEj8KBmpzdHlwZRgGIAEoDjIkLmdvb2dsZS5wcm90b2J1Zi5G",
"aWVsZE9wdGlvbnMuSlNUeXBlOglKU19OT1JNQUwSEwoEbGF6eRgFIAEoCDoF",
"ZmFsc2USHgoPdW52ZXJpZmllZF9sYXp5GA8gASgIOgVmYWxzZRIZCgpkZXBy",
"ZWNhdGVkGAMgASgIOgVmYWxzZRITCgR3ZWFrGAogASgIOgVmYWxzZRIbCgxk",
"ZWJ1Z19yZWRhY3QYECABKAg6BWZhbHNlEkAKCXJldGVudGlvbhgRIAEoDjIt",
"Lmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlvbnMuT3B0aW9uUmV0ZW50aW9u",
"Ej8KB3RhcmdldHMYEyADKA4yLi5nb29nbGUucHJvdG9idWYuRmllbGRPcHRp",
"b25zLk9wdGlvblRhcmdldFR5cGUSRgoQZWRpdGlvbl9kZWZhdWx0cxgUIAMo",
"CzIsLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlvbnMuRWRpdGlvbkRlZmF1",
"bHQSLQoIZmVhdHVyZXMYFSABKAsyGy5nb29nbGUucHJvdG9idWYuRmVhdHVy",
"ZVNldBJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUu",
"cHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbhpKCg5FZGl0aW9uRGVmYXVs",
"dBIpCgdlZGl0aW9uGAMgASgOMhguZ29vZ2xlLnByb3RvYnVmLkVkaXRpb24S",
"DQoFdmFsdWUYAiABKAkiLwoFQ1R5cGUSCgoGU1RSSU5HEAASCAoEQ09SRBAB",
"EhAKDFNUUklOR19QSUVDRRACIjUKBkpTVHlwZRINCglKU19OT1JNQUwQABIN",
"CglKU19TVFJJTkcQARINCglKU19OVU1CRVIQAiJVCg9PcHRpb25SZXRlbnRp",
"b24SFQoRUkVURU5USU9OX1VOS05PV04QABIVChFSRVRFTlRJT05fUlVOVElN",
"RRABEhQKEFJFVEVOVElPTl9TT1VSQ0UQAiKMAgoQT3B0aW9uVGFyZ2V0VHlw",
"ZRIXChNUQVJHRVRfVFlQRV9VTktOT1dOEAASFAoQVEFSR0VUX1RZUEVfRklM",
"RRABEh8KG1RBUkdFVF9UWVBFX0VYVEVOU0lPTl9SQU5HRRACEhcKE1RBUkdF",
"VF9UWVBFX01FU1NBR0UQAxIVChFUQVJHRVRfVFlQRV9GSUVMRBAEEhUKEVRB",
"UkdFVF9UWVBFX09ORU9GEAUSFAoQVEFSR0VUX1RZUEVfRU5VTRAGEhoKFlRB",
"UkdFVF9UWVBFX0VOVU1fRU5UUlkQBxIXChNUQVJHRVRfVFlQRV9TRVJWSUNF",
"EAgSFgoSVEFSR0VUX1RZUEVfTUVUSE9EEAkqCQjoBxCAgICAAkoECAQQBUoE",
"CBIQEyKNAQoMT25lb2ZPcHRpb25zEi0KCGZlYXR1cmVzGAEgASgLMhsuZ29v",
"Z2xlLnByb3RvYnVmLkZlYXR1cmVTZXQSQwoUdW5pbnRlcnByZXRlZF9vcHRp",
"b24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRp",
"b24qCQjoBxCAgICAAiL2AQoLRW51bU9wdGlvbnMSEwoLYWxsb3dfYWxpYXMY",
"AiABKAgSGQoKZGVwcmVjYXRlZBgDIAEoCDoFZmFsc2USMgomZGVwcmVjYXRl",
"ZF9sZWdhY3lfanNvbl9maWVsZF9jb25mbGljdHMYBiABKAhCAhgBEi0KCGZl",
"YXR1cmVzGAcgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkZlYXR1cmVTZXQSQwoU",
"dW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVm",
"LlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAkoECAUQBiLJAQoQRW51",
"bVZhbHVlT3B0aW9ucxIZCgpkZXByZWNhdGVkGAEgASgIOgVmYWxzZRItCghm",
"ZWF0dXJlcxgCIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJlU2V0EhsK",
"DGRlYnVnX3JlZGFjdBgDIAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9v",
"cHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRP", "cHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRP",
"cHRpb24qCQjoBxCAgICAAkoECAQQBUoECAUQBkoECAYQB0oECAgQCUoECAkQ", "cHRpb24qCQjoBxCAgICAAiKqAQoOU2VydmljZU9wdGlvbnMSLQoIZmVhdHVy",
"CiKNCQoMRmllbGRPcHRpb25zEjoKBWN0eXBlGAEgASgOMiMuZ29vZ2xlLnBy", "ZXMYIiABKAsyGy5nb29nbGUucHJvdG9idWYuRmVhdHVyZVNldBIZCgpkZXBy",
"b3RvYnVmLkZpZWxkT3B0aW9ucy5DVHlwZToGU1RSSU5HEg4KBnBhY2tlZBgC", "ZWNhdGVkGCEgASgIOgVmYWxzZRJDChR1bmludGVycHJldGVkX29wdGlvbhjn",
"IAEoCBI/CgZqc3R5cGUYBiABKA4yJC5nb29nbGUucHJvdG9idWYuRmllbGRP", "ByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbioJ",
"cHRpb25zLkpTVHlwZToJSlNfTk9STUFMEhMKBGxhenkYBSABKAg6BWZhbHNl", "COgHEICAgIACItwCCg1NZXRob2RPcHRpb25zEhkKCmRlcHJlY2F0ZWQYISAB",
"Eh4KD3VudmVyaWZpZWRfbGF6eRgPIAEoCDoFZmFsc2USGQoKZGVwcmVjYXRl", "KAg6BWZhbHNlEl8KEWlkZW1wb3RlbmN5X2xldmVsGCIgASgOMi8uZ29vZ2xl",
"ZBgDIAEoCDoFZmFsc2USEwoEd2VhaxgKIAEoCDoFZmFsc2USGwoMZGVidWdf", "LnByb3RvYnVmLk1ldGhvZE9wdGlvbnMuSWRlbXBvdGVuY3lMZXZlbDoTSURF",
"cmVkYWN0GBAgASgIOgVmYWxzZRJACglyZXRlbnRpb24YESABKA4yLS5nb29n", "TVBPVEVOQ1lfVU5LTk9XThItCghmZWF0dXJlcxgjIAEoCzIbLmdvb2dsZS5w",
"bGUucHJvdG9idWYuRmllbGRPcHRpb25zLk9wdGlvblJldGVudGlvbhI/Cgd0",
"YXJnZXRzGBMgAygOMi4uZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5P",
"cHRpb25UYXJnZXRUeXBlEkYKEGVkaXRpb25fZGVmYXVsdHMYFCADKAsyLC5n",
"b29nbGUucHJvdG9idWYuRmllbGRPcHRpb25zLkVkaXRpb25EZWZhdWx0Ei0K",
"CGZlYXR1cmVzGBUgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkZlYXR1cmVTZXQS",
"QwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3Rv",
"YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24aSgoORWRpdGlvbkRlZmF1bHQSKQoH",
"ZWRpdGlvbhgDIAEoDjIYLmdvb2dsZS5wcm90b2J1Zi5FZGl0aW9uEg0KBXZh",
"bHVlGAIgASgJIi8KBUNUeXBlEgoKBlNUUklORxAAEggKBENPUkQQARIQCgxT",
"VFJJTkdfUElFQ0UQAiI1CgZKU1R5cGUSDQoJSlNfTk9STUFMEAASDQoJSlNf",
"U1RSSU5HEAESDQoJSlNfTlVNQkVSEAIiVQoPT3B0aW9uUmV0ZW50aW9uEhUK",
"EVJFVEVOVElPTl9VTktOT1dOEAASFQoRUkVURU5USU9OX1JVTlRJTUUQARIU",
"ChBSRVRFTlRJT05fU09VUkNFEAIijAIKEE9wdGlvblRhcmdldFR5cGUSFwoT",
"VEFSR0VUX1RZUEVfVU5LTk9XThAAEhQKEFRBUkdFVF9UWVBFX0ZJTEUQARIf",
"ChtUQVJHRVRfVFlQRV9FWFRFTlNJT05fUkFOR0UQAhIXChNUQVJHRVRfVFlQ",
"RV9NRVNTQUdFEAMSFQoRVEFSR0VUX1RZUEVfRklFTEQQBBIVChFUQVJHRVRf",
"VFlQRV9PTkVPRhAFEhQKEFRBUkdFVF9UWVBFX0VOVU0QBhIaChZUQVJHRVRf",
"VFlQRV9FTlVNX0VOVFJZEAcSFwoTVEFSR0VUX1RZUEVfU0VSVklDRRAIEhYK",
"ElRBUkdFVF9UWVBFX01FVEhPRBAJKgkI6AcQgICAgAJKBAgEEAVKBAgSEBMi",
"jQEKDE9uZW9mT3B0aW9ucxItCghmZWF0dXJlcxgBIAEoCzIbLmdvb2dsZS5w",
"cm90b2J1Zi5GZWF0dXJlU2V0EkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcH", "cm90b2J1Zi5GZWF0dXJlU2V0EkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcH",
"IAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI", "IAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIlAK",
"6AcQgICAgAIi9gEKC0VudW1PcHRpb25zEhMKC2FsbG93X2FsaWFzGAIgASgI", "EElkZW1wb3RlbmN5TGV2ZWwSFwoTSURFTVBPVEVOQ1lfVU5LTk9XThAAEhMK",
"EhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNlEjIKJmRlcHJlY2F0ZWRfbGVn", "D05PX1NJREVfRUZGRUNUUxABEg4KCklERU1QT1RFTlQQAioJCOgHEICAgIAC",
"YWN5X2pzb25fZmllbGRfY29uZmxpY3RzGAYgASgIQgIYARItCghmZWF0dXJl", "Ip4CChNVbmludGVycHJldGVkT3B0aW9uEjsKBG5hbWUYAiADKAsyLS5nb29n",
"cxgHIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJlU2V0EkMKFHVuaW50", "bGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbi5OYW1lUGFydBIYChBp",
"ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5Vbmlu", "ZGVudGlmaWVyX3ZhbHVlGAMgASgJEhoKEnBvc2l0aXZlX2ludF92YWx1ZRgE",
"dGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAJKBAgFEAYiyQEKEEVudW1WYWx1", "IAEoBBIaChJuZWdhdGl2ZV9pbnRfdmFsdWUYBSABKAMSFAoMZG91YmxlX3Zh",
"ZU9wdGlvbnMSGQoKZGVwcmVjYXRlZBgBIAEoCDoFZmFsc2USLQoIZmVhdHVy", "bHVlGAYgASgBEhQKDHN0cmluZ192YWx1ZRgHIAEoDBIXCg9hZ2dyZWdhdGVf",
"ZXMYAiABKAsyGy5nb29nbGUucHJvdG9idWYuRmVhdHVyZVNldBIbCgxkZWJ1", "dmFsdWUYCCABKAkaMwoITmFtZVBhcnQSEQoJbmFtZV9wYXJ0GAEgAigJEhQK",
"Z19yZWRhY3QYAyABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9u", "DGlzX2V4dGVuc2lvbhgCIAIoCCKdCQoKRmVhdHVyZVNldBJ8Cg5maWVsZF9w",
"GOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9u", "cmVzZW5jZRgBIAEoDjIpLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJlU2V0LkZp",
"KgkI6AcQgICAgAIiqgEKDlNlcnZpY2VPcHRpb25zEi0KCGZlYXR1cmVzGCIg", "ZWxkUHJlc2VuY2VCOYgBAZgBBJgBAaIBDRIIRVhQTElDSVQY5geiAQ0SCElN",
"ASgLMhsuZ29vZ2xlLnByb3RvYnVmLkZlYXR1cmVTZXQSGQoKZGVwcmVjYXRl", "UExJQ0lUGOcHogENEghFWFBMSUNJVBjoBxJcCgllbnVtX3R5cGUYAiABKA4y",
"ZBghIAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygL", "JC5nb29nbGUucHJvdG9idWYuRmVhdHVyZVNldC5FbnVtVHlwZUIjiAEBmAEG",
"MiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCA", "mAEBogELEgZDTE9TRUQY5geiAQkSBE9QRU4Y5wcSewoXcmVwZWF0ZWRfZmll",
"gICAAiLcAgoNTWV0aG9kT3B0aW9ucxIZCgpkZXByZWNhdGVkGCEgASgIOgVm", "bGRfZW5jb2RpbmcYAyABKA4yMS5nb29nbGUucHJvdG9idWYuRmVhdHVyZVNl",
"YWxzZRJfChFpZGVtcG90ZW5jeV9sZXZlbBgiIAEoDjIvLmdvb2dsZS5wcm90", "dC5SZXBlYXRlZEZpZWxkRW5jb2RpbmdCJ4gBAZgBBJgBAaIBDRIIRVhQQU5E",
"b2J1Zi5NZXRob2RPcHRpb25zLklkZW1wb3RlbmN5TGV2ZWw6E0lERU1QT1RF", "RUQY5geiAQsSBlBBQ0tFRBjnBxJoCg91dGY4X3ZhbGlkYXRpb24YBCABKA4y",
"TkNZX1VOS05PV04SLQoIZmVhdHVyZXMYIyABKAsyGy5nb29nbGUucHJvdG9i", "Ki5nb29nbGUucHJvdG9idWYuRmVhdHVyZVNldC5VdGY4VmFsaWRhdGlvbkIj",
"dWYuRmVhdHVyZVNldBJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsy", "iAEBmAEEmAEBogEJEgROT05FGOYHogELEgZWRVJJRlkY5wcSZwoQbWVzc2Fn",
"JC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbiJQChBJZGVt", "ZV9lbmNvZGluZxgFIAEoDjIrLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJlU2V0",
"cG90ZW5jeUxldmVsEhcKE0lERU1QT1RFTkNZX1VOS05PV04QABITCg9OT19T", "Lk1lc3NhZ2VFbmNvZGluZ0IgiAEBmAEEmAEBogEUEg9MRU5HVEhfUFJFRklY",
"SURFX0VGRkVDVFMQARIOCgpJREVNUE9URU5UEAIqCQjoBxCAgICAAiKeAgoT", "RUQY5gcScAoLanNvbl9mb3JtYXQYBiABKA4yJi5nb29nbGUucHJvdG9idWYu",
"VW5pbnRlcnByZXRlZE9wdGlvbhI7CgRuYW1lGAIgAygLMi0uZ29vZ2xlLnBy", "RmVhdHVyZVNldC5Kc29uRm9ybWF0QjOIAQGYAQOYAQaYAQGiARcSEkxFR0FD",
"b3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24uTmFtZVBhcnQSGAoQaWRlbnRp", "WV9CRVNUX0VGRk9SVBjmB6IBChIFQUxMT1cY5wciXAoNRmllbGRQcmVzZW5j",
"Zmllcl92YWx1ZRgDIAEoCRIaChJwb3NpdGl2ZV9pbnRfdmFsdWUYBCABKAQS", "ZRIaChZGSUVMRF9QUkVTRU5DRV9VTktOT1dOEAASDAoIRVhQTElDSVQQARIM",
"GgoSbmVnYXRpdmVfaW50X3ZhbHVlGAUgASgDEhQKDGRvdWJsZV92YWx1ZRgG", "CghJTVBMSUNJVBACEhMKD0xFR0FDWV9SRVFVSVJFRBADIjcKCEVudW1UeXBl",
"IAEoARIUCgxzdHJpbmdfdmFsdWUYByABKAwSFwoPYWdncmVnYXRlX3ZhbHVl", "EhUKEUVOVU1fVFlQRV9VTktOT1dOEAASCAoET1BFThABEgoKBkNMT1NFRBAC",
"GAggASgJGjMKCE5hbWVQYXJ0EhEKCW5hbWVfcGFydBgBIAIoCRIUCgxpc19l", "IlYKFVJlcGVhdGVkRmllbGRFbmNvZGluZxIjCh9SRVBFQVRFRF9GSUVMRF9F",
"eHRlbnNpb24YAiACKAginQkKCkZlYXR1cmVTZXQSfAoOZmllbGRfcHJlc2Vu", "TkNPRElOR19VTktOT1dOEAASCgoGUEFDS0VEEAESDAoIRVhQQU5ERUQQAiJD",
"Y2UYASABKA4yKS5nb29nbGUucHJvdG9idWYuRmVhdHVyZVNldC5GaWVsZFBy", "Cg5VdGY4VmFsaWRhdGlvbhIbChdVVEY4X1ZBTElEQVRJT05fVU5LTk9XThAA",
"ZXNlbmNlQjmIAQGYAQSYAQGiAQ0SCEVYUExJQ0lUGOYHogENEghJTVBMSUNJ", "EgoKBlZFUklGWRACEggKBE5PTkUQAyJTCg9NZXNzYWdlRW5jb2RpbmcSHAoY",
"VBjnB6IBDRIIRVhQTElDSVQY6AcSXAoJZW51bV90eXBlGAIgASgOMiQuZ29v", "TUVTU0FHRV9FTkNPRElOR19VTktOT1dOEAASEwoPTEVOR1RIX1BSRUZJWEVE",
"Z2xlLnByb3RvYnVmLkZlYXR1cmVTZXQuRW51bVR5cGVCI4gBAZgBBpgBAaIB", "EAESDQoJREVMSU1JVEVEEAIiSAoKSnNvbkZvcm1hdBIXChNKU09OX0ZPUk1B",
"CxIGQ0xPU0VEGOYHogEJEgRPUEVOGOcHEnsKF3JlcGVhdGVkX2ZpZWxkX2Vu", "VF9VTktOT1dOEAASCQoFQUxMT1cQARIWChJMRUdBQ1lfQkVTVF9FRkZPUlQQ",
"Y29kaW5nGAMgASgOMjEuZ29vZ2xlLnByb3RvYnVmLkZlYXR1cmVTZXQuUmVw", "AioGCOgHEOkHKgYI6QcQ6gcqBgiLThCQTkoGCOcHEOgHIsACChJGZWF0dXJl",
"ZWF0ZWRGaWVsZEVuY29kaW5nQieIAQGYAQSYAQGiAQ0SCEVYUEFOREVEGOYH", "U2V0RGVmYXVsdHMSTgoIZGVmYXVsdHMYASADKAsyPC5nb29nbGUucHJvdG9i",
"ogELEgZQQUNLRUQY5wcSaAoPdXRmOF92YWxpZGF0aW9uGAQgASgOMiouZ29v", "dWYuRmVhdHVyZVNldERlZmF1bHRzLkZlYXR1cmVTZXRFZGl0aW9uRGVmYXVs",
"Z2xlLnByb3RvYnVmLkZlYXR1cmVTZXQuVXRmOFZhbGlkYXRpb25CI4gBAZgB", "dBIxCg9taW5pbXVtX2VkaXRpb24YBCABKA4yGC5nb29nbGUucHJvdG9idWYu",
"BJgBAaIBCRIETk9ORRjmB6IBCxIGVkVSSUZZGOcHEmcKEG1lc3NhZ2VfZW5j", "RWRpdGlvbhIxCg9tYXhpbXVtX2VkaXRpb24YBSABKA4yGC5nb29nbGUucHJv",
"b2RpbmcYBSABKA4yKy5nb29nbGUucHJvdG9idWYuRmVhdHVyZVNldC5NZXNz", "dG9idWYuRWRpdGlvbhp0ChhGZWF0dXJlU2V0RWRpdGlvbkRlZmF1bHQSKQoH",
"YWdlRW5jb2RpbmdCIIgBAZgBBJgBAaIBFBIPTEVOR1RIX1BSRUZJWEVEGOYH", "ZWRpdGlvbhgDIAEoDjIYLmdvb2dsZS5wcm90b2J1Zi5FZGl0aW9uEi0KCGZl",
"EnAKC2pzb25fZm9ybWF0GAYgASgOMiYuZ29vZ2xlLnByb3RvYnVmLkZlYXR1", "YXR1cmVzGAIgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkZlYXR1cmVTZXQi1QEK",
"cmVTZXQuSnNvbkZvcm1hdEIziAEBmAEDmAEGmAEBogEXEhJMRUdBQ1lfQkVT", "DlNvdXJjZUNvZGVJbmZvEjoKCGxvY2F0aW9uGAEgAygLMiguZ29vZ2xlLnBy",
"VF9FRkZPUlQY5geiAQoSBUFMTE9XGOcHIlwKDUZpZWxkUHJlc2VuY2USGgoW", "b3RvYnVmLlNvdXJjZUNvZGVJbmZvLkxvY2F0aW9uGoYBCghMb2NhdGlvbhIQ",
"RklFTERfUFJFU0VOQ0VfVU5LTk9XThAAEgwKCEVYUExJQ0lUEAESDAoISU1Q", "CgRwYXRoGAEgAygFQgIQARIQCgRzcGFuGAIgAygFQgIQARIYChBsZWFkaW5n",
"TElDSVQQAhITCg9MRUdBQ1lfUkVRVUlSRUQQAyI3CghFbnVtVHlwZRIVChFF", "X2NvbW1lbnRzGAMgASgJEhkKEXRyYWlsaW5nX2NvbW1lbnRzGAQgASgJEiEK",
"TlVNX1RZUEVfVU5LTk9XThAAEggKBE9QRU4QARIKCgZDTE9TRUQQAiJWChVS", "GWxlYWRpbmdfZGV0YWNoZWRfY29tbWVudHMYBiADKAkinAIKEUdlbmVyYXRl",
"ZXBlYXRlZEZpZWxkRW5jb2RpbmcSIwofUkVQRUFURURfRklFTERfRU5DT0RJ", "ZENvZGVJbmZvEkEKCmFubm90YXRpb24YASADKAsyLS5nb29nbGUucHJvdG9i",
"TkdfVU5LTk9XThAAEgoKBlBBQ0tFRBABEgwKCEVYUEFOREVEEAIiQwoOVXRm", "dWYuR2VuZXJhdGVkQ29kZUluZm8uQW5ub3RhdGlvbhrDAQoKQW5ub3RhdGlv",
"OFZhbGlkYXRpb24SGwoXVVRGOF9WQUxJREFUSU9OX1VOS05PV04QABIICgRO", "bhIQCgRwYXRoGAEgAygFQgIQARITCgtzb3VyY2VfZmlsZRgCIAEoCRINCgVi",
"T05FEAESCgoGVkVSSUZZEAIiUwoPTWVzc2FnZUVuY29kaW5nEhwKGE1FU1NB", "ZWdpbhgDIAEoBRILCgNlbmQYBCABKAUSSAoIc2VtYW50aWMYBSABKA4yNi5n",
"R0VfRU5DT0RJTkdfVU5LTk9XThAAEhMKD0xFTkdUSF9QUkVGSVhFRBABEg0K", "b29nbGUucHJvdG9idWYuR2VuZXJhdGVkQ29kZUluZm8uQW5ub3RhdGlvbi5T",
"CURFTElNSVRFRBACIkgKCkpzb25Gb3JtYXQSFwoTSlNPTl9GT1JNQVRfVU5L", "ZW1hbnRpYyIoCghTZW1hbnRpYxIICgROT05FEAASBwoDU0VUEAESCQoFQUxJ",
"Tk9XThAAEgkKBUFMTE9XEAESFgoSTEVHQUNZX0JFU1RfRUZGT1JUEAIqBgjo", "QVMQAir/AQoHRWRpdGlvbhITCg9FRElUSU9OX1VOS05PV04QABITCg5FRElU",
"BxDpByoGCOkHEOoHKgYIi04QkE5KBgjnBxDoByLAAgoSRmVhdHVyZVNldERl", "SU9OX1BST1RPMhDmBxITCg5FRElUSU9OX1BST1RPMxDnBxIRCgxFRElUSU9O",
"ZmF1bHRzEk4KCGRlZmF1bHRzGAEgAygLMjwuZ29vZ2xlLnByb3RvYnVmLkZl", "XzIwMjMQ6AcSFwoTRURJVElPTl8xX1RFU1RfT05MWRABEhcKE0VESVRJT05f",
"YXR1cmVTZXREZWZhdWx0cy5GZWF0dXJlU2V0RWRpdGlvbkRlZmF1bHQSMQoP", "Ml9URVNUX09OTFkQAhIdChdFRElUSU9OXzk5OTk3X1RFU1RfT05MWRCdjQYS",
"bWluaW11bV9lZGl0aW9uGAQgASgOMhguZ29vZ2xlLnByb3RvYnVmLkVkaXRp", "HQoXRURJVElPTl85OTk5OF9URVNUX09OTFkQno0GEh0KF0VESVRJT05fOTk5",
"b24SMQoPbWF4aW11bV9lZGl0aW9uGAUgASgOMhguZ29vZ2xlLnByb3RvYnVm", "OTlfVEVTVF9PTkxZEJ+NBhITCgtFRElUSU9OX01BWBD/////B0J+ChNjb20u",
"LkVkaXRpb24adAoYRmVhdHVyZVNldEVkaXRpb25EZWZhdWx0EikKB2VkaXRp", "Z29vZ2xlLnByb3RvYnVmQhBEZXNjcmlwdG9yUHJvdG9zSAFaLWdvb2dsZS5n",
"b24YAyABKA4yGC5nb29nbGUucHJvdG9idWYuRWRpdGlvbhItCghmZWF0dXJl", "b2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2Rlc2NyaXB0b3JwYvgBAaICA0dQ",
"cxgCIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJlU2V0ItUBCg5Tb3Vy", "QqoCGkdvb2dsZS5Qcm90b2J1Zi5SZWZsZWN0aW9u"));
"Y2VDb2RlSW5mbxI6Cghsb2NhdGlvbhgBIAMoCzIoLmdvb2dsZS5wcm90b2J1",
"Zi5Tb3VyY2VDb2RlSW5mby5Mb2NhdGlvbhqGAQoITG9jYXRpb24SEAoEcGF0",
"aBgBIAMoBUICEAESEAoEc3BhbhgCIAMoBUICEAESGAoQbGVhZGluZ19jb21t",
"ZW50cxgDIAEoCRIZChF0cmFpbGluZ19jb21tZW50cxgEIAEoCRIhChlsZWFk",
"aW5nX2RldGFjaGVkX2NvbW1lbnRzGAYgAygJIpwCChFHZW5lcmF0ZWRDb2Rl",
"SW5mbxJBCgphbm5vdGF0aW9uGAEgAygLMi0uZ29vZ2xlLnByb3RvYnVmLkdl",
"bmVyYXRlZENvZGVJbmZvLkFubm90YXRpb24awwEKCkFubm90YXRpb24SEAoE",
"cGF0aBgBIAMoBUICEAESEwoLc291cmNlX2ZpbGUYAiABKAkSDQoFYmVnaW4Y",
"AyABKAUSCwoDZW5kGAQgASgFEkgKCHNlbWFudGljGAUgASgOMjYuZ29vZ2xl",
"LnByb3RvYnVmLkdlbmVyYXRlZENvZGVJbmZvLkFubm90YXRpb24uU2VtYW50",
"aWMiKAoIU2VtYW50aWMSCAoETk9ORRAAEgcKA1NFVBABEgkKBUFMSUFTEAIq",
"6gEKB0VkaXRpb24SEwoPRURJVElPTl9VTktOT1dOEAASEwoORURJVElPTl9Q",
"Uk9UTzIQ5gcSEwoORURJVElPTl9QUk9UTzMQ5wcSEQoMRURJVElPTl8yMDIz",
"EOgHEhcKE0VESVRJT05fMV9URVNUX09OTFkQARIXChNFRElUSU9OXzJfVEVT",
"VF9PTkxZEAISHQoXRURJVElPTl85OTk5N19URVNUX09OTFkQnY0GEh0KF0VE",
"SVRJT05fOTk5OThfVEVTVF9PTkxZEJ6NBhIdChdFRElUSU9OXzk5OTk5X1RF",
"U1RfT05MWRCfjQZCfgoTY29tLmdvb2dsZS5wcm90b2J1ZkIQRGVzY3JpcHRv",
"clByb3Rvc0gBWi1nb29nbGUuZ29sYW5nLm9yZy9wcm90b2J1Zi90eXBlcy9k",
"ZXNjcmlwdG9ycGL4AQGiAgNHUEKqAhpHb29nbGUuUHJvdG9idWYuUmVmbGVj",
"dGlvbg=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { }, new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.Reflection.Edition), }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.Reflection.Edition), }, null, new pbr::GeneratedClrTypeInfo[] {
@ -301,6 +301,12 @@ namespace Google.Protobuf.Reflection {
[pbr::OriginalName("EDITION_99997_TEST_ONLY")] _99997TestOnly = 99997, [pbr::OriginalName("EDITION_99997_TEST_ONLY")] _99997TestOnly = 99997,
[pbr::OriginalName("EDITION_99998_TEST_ONLY")] _99998TestOnly = 99998, [pbr::OriginalName("EDITION_99998_TEST_ONLY")] _99998TestOnly = 99998,
[pbr::OriginalName("EDITION_99999_TEST_ONLY")] _99999TestOnly = 99999, [pbr::OriginalName("EDITION_99999_TEST_ONLY")] _99999TestOnly = 99999,
/// <summary>
/// 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.
/// </summary>
[pbr::OriginalName("EDITION_MAX")] Max = 2147483647,
} }
#endregion #endregion
@ -3387,12 +3393,12 @@ namespace Google.Protobuf.Reflection {
/// If true, this is a proto3 "optional". When a proto3 field is optional, it /// If true, this is a proto3 "optional". When a proto3 field is optional, it
/// tracks presence regardless of field type. /// tracks presence regardless of field type.
/// ///
/// When proto3_optional is true, this field must be belong to a oneof to /// When proto3_optional is true, this field must belong to a oneof to signal
/// signal to old proto3 clients that presence is tracked for this field. This /// to old proto3 clients that presence is tracked for this field. This oneof
/// oneof is known as a "synthetic" oneof, and this field must be its sole /// is known as a "synthetic" oneof, and this field must be its sole member
/// member (each proto3 optional field gets its own synthetic oneof). Synthetic /// (each proto3 optional field gets its own synthetic oneof). Synthetic oneofs
/// oneofs exist in the descriptor only, and do not generate any API. Synthetic /// exist in the descriptor only, and do not generate any API. Synthetic oneofs
/// oneofs must be ordered after all "real" oneofs. /// must be ordered after all "real" oneofs.
/// ///
/// For message fields, proto3_optional doesn't create any semantic change, /// For message fields, proto3_optional doesn't create any semantic change,
/// since non-repeated message fields always track presence. However it still /// since non-repeated message fields always track presence. However it still
@ -12256,8 +12262,8 @@ namespace Google.Protobuf.Reflection {
public enum Utf8Validation { public enum Utf8Validation {
[pbr::OriginalName("UTF8_VALIDATION_UNKNOWN")] Unknown = 0, [pbr::OriginalName("UTF8_VALIDATION_UNKNOWN")] Unknown = 0,
[pbr::OriginalName("NONE")] None = 1,
[pbr::OriginalName("VERIFY")] Verify = 2, [pbr::OriginalName("VERIFY")] Verify = 2,
[pbr::OriginalName("NONE")] None = 3,
} }
public enum MessageEncoding { public enum MessageEncoding {

@ -36,3 +36,4 @@ The following topics are in this repository:
* [Edition Naming](edition-naming.md) * [Edition Naming](edition-naming.md)
* [Editions Feature Visibility](editions-feature-visibility.md) * [Editions Feature Visibility](editions-feature-visibility.md)
* [Legacy Syntax Editions](legacy-syntax-editions.md) * [Legacy Syntax Editions](legacy-syntax-editions.md)
* [Editions: Feature Extension Layout](editions-feature-extension-layout.md)

@ -0,0 +1,150 @@
# Editions: Feature Extension Layout
**Author:** [@mkruskal-google](https://github.com/mkruskal-google),
[@zhangskz](https://github.com/zhangskz)
**Approved:** 2023-08-23
## Background
"[What are Protobuf Editions](what-are-protobuf-editions.md)" lays out a plan
for allowing for more targeted features not owned by the protobuf team. It uses
extensions of the global features proto to implement this. One thing that was
left a bit ambiguous was *who* should own these extensions. Language, code
generator, and runtime implementations are all similar but not identical
distinctions.
"Editions Zero Feature: utf8_validation" (not available externally, though a
later version,
"[Editions Zero: utf8_validation Without Problematic Options](editions-zero-utf8_validation.md)"
is) is a recent plan to add a new set of generator features for utf8 validation.
While the sole feature we had originally created (`legacy_closed_enum` in Java
and C++) didn't have any ambiguity here, this one did. Specifically in Python,
the current behaviors across proto2/proto3 are distinct for all 3
implementations: pure python, Python/C++, Python/upb.
## Overview
In meetings, we've discussed various alternatives, captured below. The original
plan was to make feature extensions runtime implementation-specific (e.g. C++,
Java, Python, upb). There are some notable complications that came up though:
1. **Polyglot** - it's not clear how upb or C++ runtimes should behave in
multi-language situations. Which feature sets do they consider for runtime
behaviors? *Note: this is already a serious issue today, where all proto2
strings and many proto3 strings are completely unsafe across languages.*
2. **Shared Implementations** - Runtimes like upb and C++ are used as backing
implementations of multiple other languages (e.g. Python, Rust, Ruby, PHP).
If we have a single set of `upb` or `cpp` features, migrating to those
shared implementations would be more difficult (since there's no independent
switches per-language). *Note: this is already the situation we're in today,
where switching the runtime implementation can cause subtle and dangerous
behavior changes.*
Given that we only have two behaviors, and one of them is unambiguous, it seems
reasonable to punt on this decision until we have more information. We may
encounter more edge cases that require feature extensions (and give us more
information) during the rollout of edition zero. We also have a lot of freedom
to re-model features in later editions, so keeping the initial implementation as
simple as possible seems best (i.e. Alternative 2).
## Alternatives
### Alternative 1: Runtime Implementation Features
Features would be per-runtime implementation as originally described in
"Editions Zero Feature: utf8_validation." For example, Protobuf Python users
would set different features depending on the backing implementation (e.g.
`features.(pb.cpp).<feature>`, `features.(pb.upb).<feature>`).
#### Pros
* Most consistent with range of behaviors expressible pre-Editions
#### Cons
* Implementation may / should not be obvious to users.
* Lack of levers specifically for language / implementation combos. For
example, there is no way to set Python-C++ behavior independently of C++
behavior which may make migration harder from other Python implementations.
### Alternative 2: Generator Features
Features would be per-generator only (i.e. each protoc plugin would own one set
of features). This was the second decision we made in later discussions, and
while very similar to the above alternative, it's more inline with our goal of
making features primarily for codegen.
For example, all Python implementations would share the same set of features
(e.g. `features.(pb.python).<feature>`). However, certain features could be
targeted to specific implementations (e.g.
`features.(pb.python).upb_utf8_validation` would only be used by Python/upb).
#### Pros
* Allows independent controls of shared implementations in different target
languages (e.g. Python's upb feature won't affect PHP).
#### Cons
* Possible complexity in upb to understand which language's features to
respect. UPB is not currently aware of what language it is being used for.
* Limits in-process sharing across languages with shared implementations (e.g.
Python upb, PHP upb) in the case of conflicting behaviors.
* Additional checks may be needed.
### Alternative 3: Migrate to bytes
Since this whole discussion revolves around the utf8 validation feature, one
option would be to just remove it from edition zero. Instead of adding a new
toggle for UTF8 behavior, we could simply migrate everyone who doesn't enforce
utf8 today to `bytes`. This would likely need another new *codegen* feature for
generating byte getters/setters as strings, but that wouldn't have any of the
ambiguity we're seeing today.
Unfortunately, this doesn't seem feasible because of all the different behaviors
laid out in "Editions Zero Feature: utf8_validation." UTF8 validation isn't
really a binary on/off decision, and it can vary widely between languages. There
are many cases where UTF8 is validated in **some** languages but not others, and
there's also the C++ "hint" behavior that logs errors but allows invalid UTF8.
**Note:** This could still be partially done in a follow-up LSC by targeting
specific combinations of the new feature that disable validation in all relevant
languages.
#### Pros
* Punts on the issue, we wouldn't need any upb features and C++ features would
all be code-gen only
* Simplifies the situation, avoids adding a very complicated feature in
edition zero
#### Cons
* Not really possible given the current complexity
* There are O(10M) proto2 string fields that would be blindly changed to bytes
### Alternative 4: Nested Features
Another option is to allow for shared feature set messages. For example, upb
would define a feature message, but *not* make it an extension of the global
`FeatureSet`. Instead, languages with upb implementations would have a field of
this type to allow for finer-grained controls. C++ would both extend the global
`FeatureSet` and also be allowed as a field in other languages.
For example, python utf8 validation could be specified as:
We could have checks during feature validation that enforce that impossible
combinations aren't specified. For example, with our current implementation
`features.(pb.python).cpp` should always be identical to `features.(pb.cpp)`,
since we don't have any mechanism for distinguishing them.
#### Pros
* Much more explicit than options 1 and 2
#### Cons
* Maybe too explicit? Proto owners would be forced to duplicate a lot of
features

@ -0,0 +1,138 @@
# Prototiller Requirements for Editions
**Author:** [@mcy](https://github.com/mcy)
**Approved:** 2022-11-29
## Background
Prototiller is Protobuf's new mass refactoring Swiss army knife, similar to
Buildozer. We plan to use Prototiller to enable LSCs within google3 and to allow
users (internal and external) to modify `.proto` files safely.
Prototiller is being developed as part of the
[Editions](../editions/what-are-protobuf-editions.md) project, and will
prioritize enabling Editions-related refactorings to unblock Editions migrations
in 2023. This document describes the relevant requirements.
## Overview
*Protochangifier Semantic Actions* (not available externally) describes the
original design for the Prototiller interface; it would consume a Protobuf
message that described changes to apply to a `.proto` file passed as input. In
this document, we prescribe a variant of this interface that fulfills *only* the
needs of Editions, while remaining extensible for future change actions.
Broad requirements are as follows:
* Actions must include the following Editions-oriented upgrade workflows:
* Upgrade a file to a particular edition, regardless of whether it's in
syntax mode or editions mode, updating features in such a way to be a
no-op. **This is the highest-priority workflow.**
* "Clean up" features in a particular file: i.e., run a simple algorithm
to determine the smallest set of features that need to be present at
each level of the file.
* Modify features from a particular syntax element.
* Actions must be both specific to particular syntax elements (for when change
specs are checked in alongside `.proto` files by Schema Consumers), and
generic (so that a single change spec or set of change specs can power a
large-scale change).
In this document we provide a recommendation for a Protobuf schema based on the
original Protochangifier design, but geared towards these specific needs.
This is only a recommendation; the Prototiller project owners should modify this
to suit the implementation; only the requirements in this document are binding,
and the schema is merely an illustration of those requirements.
The suggested schema is as follows.
```
syntax = "proto2";
package prototiller;
// This is the proto that Prototiller accepts as input.
message ChangeSpec {
// Actions to execute on the file.
repeated Action actions = 1;
// Some changes may result in a wireformat break; changing field type is
// usually unsafe. By default, Prototiller does not allow such changes,
// users can set allow_unsafe_wire_format_changes to true to force the change.
optional bool allow_unsafe_wire_format_changes = 2 [default = false];
optional bool allow_unsafe_text_format_changes = 3 [default = false];
optional bool allow_unsafe_json_format_changes = 4 [default = false];
}
// A single action. See messages below for description of their
// semantics.
message Action {
oneof kind {
UpgradeEdition upgrade_edition = 20;
CleanUpFeatures clean_up_features = 21;
ModifyFeature modify_feature = 22;
}
}
// Upgrades the edition of a file to a specified edition.
// Treats syntax mode as being a weird, special edition that cannot be
// upgraded to.
//
// This action is always safe.
message UpgradeEdition {
// The edition to upgrade to.
optional string edition = 1;
}
// Cleans up features in a file, such that there are as few explicitly set
// features as necessary.
//
// This action is always safe.
message CleanUpFeatures {}
// Modifies a specific feature on all syntax elements that match and which can
// host that particular feature.
//
// Prototiller must be aware of which changes affect wire format, so that it
// can flag them as unsafe.
message ModifyFeature {
// The name of the feature to modify.
repeated proto2.UninterpretedOption.NamePart feature = 1;
// A pattern for matching paths to syntax elements to modify.
//
// Elements of this field can either be identifiers, or the string "*", which
// matches all identifiers. Thus, ["foo", "Bar"] matches the message foo.Bar,
// ["foo", "Bar", "*"] matches all fields and nested types of foo.Bar
// (recursively), and ["*"] matches all elements of a file.
repeated string path_pattern = 2;
// The value to set the feature to. If not set, this means that the
// feature should be deleted.
oneof value {
int64 int_value = 20;
double double_value = 21;
// ... and so on.
}
}
```
## Alternatives Considered
This document does not capture a design so much as requirements that a design
must satisfy, so we will be brief on potential alternatives to the requirements,
and why we decided against them.
* Omit feature cleanup as its own action, and let it happen implicitly as part
of other actions.
* It is desirable to be able to aggressively run this operation
everywhere, potentially even as part of "format on save" in Cider and
other IDEs.
* Make `ModifyFeature` operate on all syntax elements of a file
simultaneously.
* `ModifyFeature` is intended so that SchemaConsumers can affect
fine-grained control of features in `.proto` files they import. Users
will want to be able to wipe out a feature from all fields in a file, or
perhaps just on a handful of fields they care about. Offering simple
pattern-matching supports both.

@ -486,3 +486,8 @@ with info about your project (name and website) so we can add an entry for you.
* Website: https://square.github.io/wire/ * Website: https://square.github.io/wire/
* Extensions: 1185 * Extensions: 1185
1. Protons
* Website: https://github.com/ipfs/protons
* Extensions: 1186

@ -169,9 +169,7 @@ Inactive:
* https://github.com/thesamet/rpcz (C++/Python, based on ZeroMQ) * https://github.com/thesamet/rpcz (C++/Python, based on ZeroMQ)
* https://github.com/w359405949/libmaid (C++, Python) * https://github.com/w359405949/libmaid (C++, Python)
## Other Utilities ## Build
There are miscellaneous other things you may find useful as a Protocol Buffers developer.
* [Bazel Build](https://bazel.build) * [Bazel Build](https://bazel.build)
* [rules_closure](https://github.com/bazelbuild/rules_closure) * [rules_closure](https://github.com/bazelbuild/rules_closure)
@ -179,17 +177,6 @@ There are miscellaneous other things you may find useful as a Protocol Buffers d
* [rules_go](https://github.com/bazelbuild/rules_go) `go` * [rules_go](https://github.com/bazelbuild/rules_go) `go`
* [rules_protobuf](https://github.com/pubref/rules_protobuf) `java` `c++` * [rules_protobuf](https://github.com/pubref/rules_protobuf) `java` `c++`
`c#` `go` `js-closure` `js-node` `python` `ruby` `c#` `go` `js-closure` `js-node` `python` `ruby`
* [NetBeans IDE plugin](https://code.google.com/p/protobuf-netbeans-plugin/)
* [Wireshark/Ethereal packet sniffer plugin](https://code.google.com/p/protobuf-wireshark/)
* [Alternate encodings (JSON, XML, HTML) for Java protobufs](https://code.google.com/p/protobuf-java-format/)
* [Another JSON encoder/decoder for Java](https://github.com/sijuv/protobuf-codec)
* [Editor for serialized protobufs](https://code.google.com/p/protobufeditor/)
* [IntelliJ IDEA plugin](http://github.com/jvolkman/intellij-protobuf-editor)
* [IntelliJ Protobuf Plugin](https://github.com/devkanro/intellij-protobuf-plugin)
* [TextMate syntax highlighting](http://github.com/michaeledgar/protobuf-tmbundle)
* [Oracle PL SQL plugin](https://code.google.com/p/protocol-buffer-plsql/)
* [Eclipse editor for protobuf (from Google)](https://code.google.com/p/protobuf-dt/)
* [C++ Builder compatible protobuf](https://github.com/saadware/protobuf-cppbuilder)
* Maven Protobuf Compiler Plugin * Maven Protobuf Compiler Plugin
* By xolstice.org * By xolstice.org
([Documentation](https://www.xolstice.org/protobuf-maven-plugin/)) ([Documentation](https://www.xolstice.org/protobuf-maven-plugin/))
@ -197,21 +184,43 @@ There are miscellaneous other things you may find useful as a Protocol Buffers d
[![Maven Central](https://img.shields.io/maven-central/v/org.xolstice.maven.plugins/protobuf-maven-plugin.svg)](https://repo1.maven.org/maven2/org/xolstice/maven/plugins/protobuf-maven-plugin/) [![Maven Central](https://img.shields.io/maven-central/v/org.xolstice.maven.plugins/protobuf-maven-plugin.svg)](https://repo1.maven.org/maven2/org/xolstice/maven/plugins/protobuf-maven-plugin/)
* https://code.google.com/p/maven-protoc-plugin/ * https://code.google.com/p/maven-protoc-plugin/
* https://github.com/os72/protoc-jar-maven-plugin * https://github.com/os72/protoc-jar-maven-plugin
* [Protobuf Plugin for Gradle](https://github.com/google/protobuf-gradle-plugin)
* [Sbt plugin for Protocol Buffers](https://github.com/Atry/sbt-cppp)
## IDE
* [Visual Studio Code Support for Protocol Buffers](https://marketplace.visualstudio.com/items?itemName=zxh404.vscode-proto3)
* [Visual Studio Language Service support for Protocol Buffers](http://visualstudiogallery.msdn.microsoft.com/4bc0f38c-b058-4e05-ae38-155e053c19c5)
* [IntelliJ IDEA plugin](http://github.com/jvolkman/intellij-protobuf-editor)
* [IntelliJ Protobuf Plugin](https://github.com/devkanro/intellij-protobuf-plugin)
* [TextMate syntax highlighting](http://github.com/michaeledgar/protobuf-tmbundle)
* [Notepad++ Syntax Highlighting for .proto files](https://github.com/chai2010/notepadplus-protobuf)
* [Eclipse editor for protobuf (from Google)](https://code.google.com/p/protobuf-dt/)
* [NetBeans IDE plugin](https://code.google.com/p/protobuf-netbeans-plugin/)
* [Editor for serialized protobufs](https://code.google.com/p/protobufeditor/)
## Documentation
* [Documentation generator plugin (Markdown/HTML/DocBook/...)](https://github.com/pseudomuto/protoc-gen-doc) * [Documentation generator plugin (Markdown/HTML/DocBook/...)](https://github.com/pseudomuto/protoc-gen-doc)
* [DocBook generator for .proto files](https://code.google.com/p/protoc-gen-docbook/) * [DocBook generator for .proto files](https://code.google.com/p/protoc-gen-docbook/)
## Other Utilities
There are miscellaneous other things you may find useful as a Protocol Buffers developer.
* [Wireshark/Ethereal packet sniffer plugin](https://code.google.com/p/protobuf-wireshark/)
* [Alternate encodings (JSON, XML, HTML) for Java protobufs](https://code.google.com/p/protobuf-java-format/)
* [Another JSON encoder/decoder for Java](https://github.com/sijuv/protobuf-codec)
* [Oracle PL SQL plugin](https://code.google.com/p/protocol-buffer-plsql/)
* [C++ Builder compatible protobuf](https://github.com/saadware/protobuf-cppbuilder)
* [Protobuf for nginx module](https://github.com/dbcode/protobuf-nginx/) * [Protobuf for nginx module](https://github.com/dbcode/protobuf-nginx/)
* [RSpec matchers and Cucumber step defs for testing Protocol Buffers](https://github.com/connamara/protobuf_spec) * [RSpec matchers and Cucumber step defs for testing Protocol Buffers](https://github.com/connamara/protobuf_spec)
* [Sbt plugin for Protocol Buffers](https://github.com/Atry/sbt-cppp)
* [Protobuf Plugin for Gradle](https://github.com/google/protobuf-gradle-plugin)
* [Multi-platform executable JAR and Java API for protoc](https://github.com/os72/protoc-jar) * [Multi-platform executable JAR and Java API for protoc](https://github.com/os72/protoc-jar)
* [Python scripts to convert between Protocol Buffers and JSON](https://github.com/NextTuesday/py-pb-converters) * [Python scripts to convert between Protocol Buffers and JSON](https://github.com/NextTuesday/py-pb-converters)
* [Visual Studio Language Service support for Protocol Buffers](http://visualstudiogallery.msdn.microsoft.com/4bc0f38c-b058-4e05-ae38-155e053c19c5)
* [Visual Studio Code Support for Protocol Buffers](https://marketplace.visualstudio.com/items?itemName=zxh404.vscode-proto3)
* [C++ library for serialization/de-serialization between Protocol Buffers and * [C++ library for serialization/de-serialization between Protocol Buffers and
JSON.](https://github.com/yinqiwen/pbjson) JSON.](https://github.com/yinqiwen/pbjson)
* [ProtoBuf with Java EE7 Expression Language 3.0; pure Java ProtoBuf Parser * [ProtoBuf with Java EE7 Expression Language 3.0; pure Java ProtoBuf Parser
and Builder.](https://github.com/protobufel/protobuf-el) and Builder.](https://github.com/protobufel/protobuf-el)
* [Notepad++ Syntax Highlighting for .proto files](https://github.com/chai2010/notepadplus-protobuf)
* [Linter for .proto files](https://github.com/ckaznocha/protoc-gen-lint) * [Linter for .proto files](https://github.com/ckaznocha/protoc-gen-lint)
* [Protocol Buffers Dynamic Schema - create protobuf schemas programmatically * [Protocol Buffers Dynamic Schema - create protobuf schemas programmatically
(Java)](https://github.com/os72/protobuf-dynamic) (Java)](https://github.com/os72/protobuf-dynamic)

@ -23,7 +23,7 @@ If you are using Maven, use the following:
<dependency> <dependency>
<groupId>com.google.protobuf</groupId> <groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId> <artifactId>protobuf-java</artifactId>
<version>3.24.0</version> <version>3.25.0</version>
</dependency> </dependency>
``` ```
@ -37,14 +37,14 @@ protobuf-java-util package:
<dependency> <dependency>
<groupId>com.google.protobuf</groupId> <groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId> <artifactId>protobuf-java-util</artifactId>
<version>3.24.0</version> <version>3.25.0</version>
</dependency> </dependency>
``` ```
### Gradle ### Gradle
If you are using Gradle, add the following to your `build.gradle` file's If you are using Gradle, add the following to your `build.gradle` file's
dependencies: `implementation 'com.google.protobuf:protobuf-java:3.24.0'` Again, dependencies: `implementation 'com.google.protobuf:protobuf-java:3.25.0'` Again,
be sure to check that the version number matches (or is newer than) the version be sure to check that the version number matches (or is newer than) the version
number of protoc that you are using. number of protoc that you are using.

@ -4,7 +4,7 @@
<groupId>com.google.protobuf</groupId> <groupId>com.google.protobuf</groupId>
<artifactId>protobuf-bom</artifactId> <artifactId>protobuf-bom</artifactId>
<version>3.24.0</version> <version>3.25.0</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>Protocol Buffers [BOM]</name> <name>Protocol Buffers [BOM]</name>

@ -2,10 +2,10 @@ load("@bazel_skylib//rules:build_test.bzl", "build_test")
load("@rules_java//java:defs.bzl", "java_lite_proto_library", "java_proto_library") load("@rules_java//java:defs.bzl", "java_lite_proto_library", "java_proto_library")
load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix") load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain", "proto_library") load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain", "proto_library")
load("//build_defs:java_opts.bzl", "protobuf_java_export", "protobuf_java_library", "protobuf_versioned_java_library")
load("//conformance:defs.bzl", "conformance_test")
load("//:protobuf.bzl", "internal_gen_well_known_protos_java") load("//:protobuf.bzl", "internal_gen_well_known_protos_java")
load("//:protobuf_version.bzl", "PROTOBUF_JAVA_VERSION") load("//:protobuf_version.bzl", "PROTOBUF_JAVA_VERSION")
load("//build_defs:java_opts.bzl", "protobuf_java_export", "protobuf_java_library", "protobuf_versioned_java_library")
load("//conformance:defs.bzl", "conformance_test")
load("//java/internal:testing.bzl", "junit_tests") load("//java/internal:testing.bzl", "junit_tests")
LITE_SRCS = [ LITE_SRCS = [
@ -85,6 +85,7 @@ LITE_SRCS = [
"src/main/java/com/google/protobuf/RawMessageInfo.java", "src/main/java/com/google/protobuf/RawMessageInfo.java",
"src/main/java/com/google/protobuf/Reader.java", "src/main/java/com/google/protobuf/Reader.java",
"src/main/java/com/google/protobuf/RopeByteString.java", "src/main/java/com/google/protobuf/RopeByteString.java",
"src/main/java/com/google/protobuf/RuntimeVersion.java",
"src/main/java/com/google/protobuf/Schema.java", "src/main/java/com/google/protobuf/Schema.java",
"src/main/java/com/google/protobuf/SchemaFactory.java", "src/main/java/com/google/protobuf/SchemaFactory.java",
"src/main/java/com/google/protobuf/SchemaUtil.java", "src/main/java/com/google/protobuf/SchemaUtil.java",
@ -136,6 +137,7 @@ protobuf_versioned_java_library(
srcs = LITE_SRCS + [ srcs = LITE_SRCS + [
":gen_well_known_protos_javalite", ":gen_well_known_protos_javalite",
], ],
automatic_module_name = "com.google.protobuf",
bundle_description = "Lite version of Protocol Buffers library. This " + bundle_description = "Lite version of Protocol Buffers library. This " +
"version is optimized for code size, but does not " + "version is optimized for code size, but does not " +
"guarantee API/ABI stability.", "guarantee API/ABI stability.",
@ -217,6 +219,7 @@ protobuf_versioned_java_library(
) + [ ) + [
":gen_well_known_protos_java", ":gen_well_known_protos_java",
], ],
automatic_module_name = "com.google.protobuf",
bundle_description = "Core Protocol Buffers library. Protocol Buffers " + bundle_description = "Core Protocol Buffers library. Protocol Buffers " +
"are a way of encoding structured data in an " + "are a way of encoding structured data in an " +
"efficient yet extensible format.", "efficient yet extensible format.",
@ -470,6 +473,7 @@ LITE_TEST_EXCLUSIONS = [
"src/test/java/com/google/protobuf/FieldPresenceTest.java", "src/test/java/com/google/protobuf/FieldPresenceTest.java",
"src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java", "src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java",
"src/test/java/com/google/protobuf/GeneratedMessageTest.java", "src/test/java/com/google/protobuf/GeneratedMessageTest.java",
"src/test/java/com/google/protobuf/LazilyParsedMessageSetTest.java",
"src/test/java/com/google/protobuf/LazyFieldTest.java", "src/test/java/com/google/protobuf/LazyFieldTest.java",
"src/test/java/com/google/protobuf/LazyStringEndToEndTest.java", "src/test/java/com/google/protobuf/LazyStringEndToEndTest.java",
"src/test/java/com/google/protobuf/MapForProto2Test.java", "src/test/java/com/google/protobuf/MapForProto2Test.java",
@ -483,6 +487,7 @@ LITE_TEST_EXCLUSIONS = [
"src/test/java/com/google/protobuf/Proto2SchemaTest.java", "src/test/java/com/google/protobuf/Proto2SchemaTest.java",
"src/test/java/com/google/protobuf/Proto2UnknownEnumValueTest.java", "src/test/java/com/google/protobuf/Proto2UnknownEnumValueTest.java",
"src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java", "src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java",
"src/test/java/com/google/protobuf/RuntimeVersionTest.java",
"src/test/java/com/google/protobuf/ServiceTest.java", "src/test/java/com/google/protobuf/ServiceTest.java",
"src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java", "src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java",
"src/test/java/com/google/protobuf/TestBadIdentifiers.java", "src/test/java/com/google/protobuf/TestBadIdentifiers.java",

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.google.protobuf</groupId> <groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId> <artifactId>protobuf-parent</artifactId>
<version>3.24.0</version> <version>3.25.0</version>
</parent> </parent>
<artifactId>protobuf-java</artifactId> <artifactId>protobuf-java</artifactId>

@ -538,44 +538,4 @@ public abstract class AbstractMessage
return (BuilderType) super.mergeFrom(input, extensionRegistry); return (BuilderType) super.mergeFrom(input, extensionRegistry);
} }
} }
/**
* @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1
* generated code.
*/
@Deprecated
protected static int hashLong(long n) {
return (int) (n ^ (n >>> 32));
}
/**
* @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1
* generated code.
*/
@Deprecated
protected static int hashBoolean(boolean b) {
return b ? 1231 : 1237;
}
/**
* @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1
* generated code.
*/
@Deprecated
protected static int hashEnum(EnumLite e) {
return e.getNumber();
}
/**
* @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1
* generated code.
*/
@Deprecated
protected static int hashEnumList(List<? extends EnumLite> list) {
int hash = 1;
for (EnumLite e : list) {
hash = 31 * hash + hashEnum(e);
}
return hash;
}
} }

@ -140,8 +140,6 @@ public final class Descriptors {
} }
/** The syntax of the .proto file. */ /** The syntax of the .proto file. */
@Deprecated
public
enum Syntax { enum Syntax {
UNKNOWN("unknown"), UNKNOWN("unknown"),
PROTO2("proto2"), PROTO2("proto2"),
@ -156,8 +154,6 @@ public final class Descriptors {
} }
/** Get the syntax of the .proto file. */ /** Get the syntax of the .proto file. */
@Deprecated
public
Syntax getSyntax() { Syntax getSyntax() {
if (Syntax.PROTO3.name.equals(proto.getSyntax())) { if (Syntax.PROTO3.name.equals(proto.getSyntax())) {
return Syntax.PROTO3; return Syntax.PROTO3;
@ -605,6 +601,15 @@ public final class Descriptors {
pool.addSymbol(message); pool.addSymbol(message);
} }
/**
* This method is to be called by generated code only. It resolves features for the descriptor
* and all of its children.
*
* <p>TODO Implement and use this method in gencode once users using prebuilt jars
* with stale runtimes updated.
*/
public void resolveAllFeatures() {}
/** Look up and cross-link all field types, etc. */ /** Look up and cross-link all field types, etc. */
private void crossLink() throws DescriptorValidationException { private void crossLink() throws DescriptorValidationException {
for (final Descriptor messageType : messageTypes) { for (final Descriptor messageType : messageTypes) {
@ -1264,8 +1269,6 @@ public final class Descriptors {
* Returns true if this field was syntactically written with "optional" in the .proto file. * Returns true if this field was syntactically written with "optional" in the .proto file.
* Excludes singular proto3 fields that do not have a label. * Excludes singular proto3 fields that do not have a label.
*/ */
@Deprecated
public
boolean hasOptionalKeyword() { boolean hasOptionalKeyword() {
return isProto3Optional return isProto3Optional
|| (file.getSyntax() == Syntax.PROTO2 && isOptional() && getContainingOneof() == null); || (file.getSyntax() == Syntax.PROTO2 && isOptional() && getContainingOneof() == null);
@ -2834,8 +2837,6 @@ public final class Descriptors {
return proto; return proto;
} }
@Deprecated
public
boolean isSynthetic() { boolean isSynthetic() {
return fields.length == 1 && fields[0].isProto3Optional; return fields.length == 1 && fields[0].isProto3Optional;
} }

@ -173,7 +173,8 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
/** Get a simple map containing all the fields. */ /** Get a simple map containing all the fields. */
public Map<T, Object> getAllFields() { public Map<T, Object> getAllFields() {
if (hasLazyField) { if (hasLazyField) {
SmallSortedMap<T, Object> result = cloneAllFieldsMap(fields, /* copyList */ false); SmallSortedMap<T, Object> result =
cloneAllFieldsMap(fields, /* copyList= */ false, /* resolveLazyFields= */ true);
if (fields.isImmutable()) { if (fields.isImmutable()) {
result.makeImmutable(); result.makeImmutable();
} }
@ -183,22 +184,22 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
} }
private static <T extends FieldDescriptorLite<T>> SmallSortedMap<T, Object> cloneAllFieldsMap( private static <T extends FieldDescriptorLite<T>> SmallSortedMap<T, Object> cloneAllFieldsMap(
SmallSortedMap<T, Object> fields, boolean copyList) { SmallSortedMap<T, Object> fields, boolean copyList, boolean resolveLazyFields) {
SmallSortedMap<T, Object> result = SmallSortedMap.newFieldMap(DEFAULT_FIELD_MAP_ARRAY_SIZE); SmallSortedMap<T, Object> result = SmallSortedMap.newFieldMap(DEFAULT_FIELD_MAP_ARRAY_SIZE);
for (int i = 0; i < fields.getNumArrayEntries(); i++) { for (int i = 0; i < fields.getNumArrayEntries(); i++) {
cloneFieldEntry(result, fields.getArrayEntryAt(i), copyList); cloneFieldEntry(result, fields.getArrayEntryAt(i), copyList, resolveLazyFields);
} }
for (Map.Entry<T, Object> entry : fields.getOverflowEntries()) { for (Map.Entry<T, Object> entry : fields.getOverflowEntries()) {
cloneFieldEntry(result, entry, copyList); cloneFieldEntry(result, entry, copyList, resolveLazyFields);
} }
return result; return result;
} }
private static <T extends FieldDescriptorLite<T>> void cloneFieldEntry( private static <T extends FieldDescriptorLite<T>> void cloneFieldEntry(
Map<T, Object> map, Map.Entry<T, Object> entry, boolean copyList) { Map<T, Object> map, Map.Entry<T, Object> entry, boolean copyList, boolean resolveLazyFields) {
T key = entry.getKey(); T key = entry.getKey();
Object value = entry.getValue(); Object value = entry.getValue();
if (value instanceof LazyField) { if (resolveLazyFields && value instanceof LazyField) {
map.put(key, ((LazyField) value).getValue()); map.put(key, ((LazyField) value).getValue());
} else if (copyList && value instanceof List) { } else if (copyList && value instanceof List) {
map.put(key, new ArrayList<>((List<?>) value)); map.put(key, new ArrayList<>((List<?>) value));
@ -500,11 +501,12 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
private void mergeFromField(final Map.Entry<T, Object> entry) { private void mergeFromField(final Map.Entry<T, Object> entry) {
final T descriptor = entry.getKey(); final T descriptor = entry.getKey();
Object otherValue = entry.getValue(); Object otherValue = entry.getValue();
if (otherValue instanceof LazyField) { boolean isLazyField = otherValue instanceof LazyField;
otherValue = ((LazyField) otherValue).getValue();
}
if (descriptor.isRepeated()) { if (descriptor.isRepeated()) {
if (isLazyField) {
throw new IllegalStateException("Lazy fields can not be repeated");
}
Object value = getField(descriptor); Object value = getField(descriptor);
if (value == null) { if (value == null) {
value = new ArrayList<>(); value = new ArrayList<>();
@ -516,9 +518,17 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
} else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
Object value = getField(descriptor); Object value = getField(descriptor);
if (value == null) { if (value == null) {
// New field.
fields.put(descriptor, cloneIfMutable(otherValue)); fields.put(descriptor, cloneIfMutable(otherValue));
if (isLazyField) {
hasLazyField = true;
}
} else { } else {
// Merge the messages. // There is an existing field. Need to merge the messages.
if (otherValue instanceof LazyField) {
// Extract the actual value for lazy fields.
otherValue = ((LazyField) otherValue).getValue();
}
value = value =
descriptor descriptor
.internalMergeFrom(((MessageLite) value).toBuilder(), (MessageLite) otherValue) .internalMergeFrom(((MessageLite) value).toBuilder(), (MessageLite) otherValue)
@ -526,6 +536,9 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
fields.put(descriptor, value); fields.put(descriptor, value);
} }
} else { } else {
if (isLazyField) {
throw new IllegalStateException("Lazy fields must be message-valued");
}
fields.put(descriptor, cloneIfMutable(otherValue)); fields.put(descriptor, cloneIfMutable(otherValue));
} }
} }
@ -946,7 +959,8 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
SmallSortedMap<T, Object> fieldsForBuild = fields; SmallSortedMap<T, Object> fieldsForBuild = fields;
if (hasNestedBuilders) { if (hasNestedBuilders) {
// Make a copy of the fields map with all Builders replaced by Message. // Make a copy of the fields map with all Builders replaced by Message.
fieldsForBuild = cloneAllFieldsMap(fields, /* copyList */ false); fieldsForBuild =
cloneAllFieldsMap(fields, /* copyList= */ false, /* resolveLazyFields= */ false);
replaceBuilders(fieldsForBuild, partial); replaceBuilders(fieldsForBuild, partial);
} }
FieldSet<T> fieldSet = new FieldSet<>(fieldsForBuild); FieldSet<T> fieldSet = new FieldSet<>(fieldsForBuild);
@ -1018,7 +1032,10 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
/** Returns a new Builder using the fields from {@code fieldSet}. */ /** Returns a new Builder using the fields from {@code fieldSet}. */
public static <T extends FieldDescriptorLite<T>> Builder<T> fromFieldSet(FieldSet<T> fieldSet) { public static <T extends FieldDescriptorLite<T>> Builder<T> fromFieldSet(FieldSet<T> fieldSet) {
Builder<T> builder = new Builder<T>(cloneAllFieldsMap(fieldSet.fields, /* copyList */ true)); Builder<T> builder =
new Builder<T>(
cloneAllFieldsMap(
fieldSet.fields, /* copyList= */ true, /* resolveLazyFields= */ false));
builder.hasLazyField = fieldSet.hasLazyField; builder.hasLazyField = fieldSet.hasLazyField;
return builder; return builder;
} }
@ -1028,7 +1045,8 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
/** Get a simple map containing all the fields. */ /** Get a simple map containing all the fields. */
public Map<T, Object> getAllFields() { public Map<T, Object> getAllFields() {
if (hasLazyField) { if (hasLazyField) {
SmallSortedMap<T, Object> result = cloneAllFieldsMap(fields, /* copyList */ false); SmallSortedMap<T, Object> result =
cloneAllFieldsMap(fields, /* copyList= */ false, /* resolveLazyFields= */ true);
if (fields.isImmutable()) { if (fields.isImmutable()) {
result.makeImmutable(); result.makeImmutable();
} else { } else {
@ -1069,7 +1087,7 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
private void ensureIsMutable() { private void ensureIsMutable() {
if (!isMutable) { if (!isMutable) {
fields = cloneAllFieldsMap(fields, /* copyList */ true); fields = cloneAllFieldsMap(fields, /* copyList= */ true, /* resolveLazyFields= */ false);
isMutable = true; isMutable = true;
} }
} }
@ -1274,11 +1292,12 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
private void mergeFromField(final Map.Entry<T, Object> entry) { private void mergeFromField(final Map.Entry<T, Object> entry) {
final T descriptor = entry.getKey(); final T descriptor = entry.getKey();
Object otherValue = entry.getValue(); Object otherValue = entry.getValue();
if (otherValue instanceof LazyField) { boolean isLazyField = otherValue instanceof LazyField;
otherValue = ((LazyField) otherValue).getValue();
}
if (descriptor.isRepeated()) { if (descriptor.isRepeated()) {
if (isLazyField) {
throw new IllegalStateException("Lazy fields can not be repeated");
}
List<Object> value = (List<Object>) getFieldAllowBuilders(descriptor); List<Object> value = (List<Object>) getFieldAllowBuilders(descriptor);
if (value == null) { if (value == null) {
value = new ArrayList<>(); value = new ArrayList<>();
@ -1290,9 +1309,17 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
} else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
Object value = getFieldAllowBuilders(descriptor); Object value = getFieldAllowBuilders(descriptor);
if (value == null) { if (value == null) {
// New field.
fields.put(descriptor, FieldSet.cloneIfMutable(otherValue)); fields.put(descriptor, FieldSet.cloneIfMutable(otherValue));
if (isLazyField) {
hasLazyField = true;
}
} else { } else {
// Merge the messages. // There is an existing field. Need to merge the messages.
if (otherValue instanceof LazyField) {
// Extract the actual value for lazy fields.
otherValue = ((LazyField) otherValue).getValue();
}
if (value instanceof MessageLite.Builder) { if (value instanceof MessageLite.Builder) {
descriptor.internalMergeFrom((MessageLite.Builder) value, (MessageLite) otherValue); descriptor.internalMergeFrom((MessageLite.Builder) value, (MessageLite) otherValue);
} else { } else {
@ -1304,6 +1331,9 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
} }
} }
} else { } else {
if (isLazyField) {
throw new IllegalStateException("Lazy fields must be message-valued");
}
fields.put(descriptor, cloneIfMutable(otherValue)); fields.put(descriptor, cloneIfMutable(otherValue));
} }
} }

@ -1440,7 +1440,7 @@ public abstract class GeneratedMessageLite<
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
throw new RuntimeException("Unable to find proto buffer class: " + messageClassName, e); throw new RuntimeException("Unable to find proto buffer class: " + messageClassName, e);
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
return readResolveFallback(); throw new RuntimeException("Unable to find DEFAULT_INSTANCE in " + messageClassName, e);
} catch (SecurityException e) { } catch (SecurityException e) {
throw new RuntimeException("Unable to call DEFAULT_INSTANCE in " + messageClassName, e); throw new RuntimeException("Unable to call DEFAULT_INSTANCE in " + messageClassName, e);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
@ -1450,33 +1450,6 @@ public abstract class GeneratedMessageLite<
} }
} }
/**
* @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1 generated code.
*/
@Deprecated
private Object readResolveFallback() throws ObjectStreamException {
try {
Class<?> messageClass = resolveMessageClass();
java.lang.reflect.Field defaultInstanceField =
messageClass.getDeclaredField("defaultInstance");
defaultInstanceField.setAccessible(true);
MessageLite defaultInstance = (MessageLite) defaultInstanceField.get(null);
return defaultInstance.newBuilderForType()
.mergeFrom(asBytes)
.buildPartial();
} catch (ClassNotFoundException e) {
throw new RuntimeException("Unable to find proto buffer class: " + messageClassName, e);
} catch (NoSuchFieldException e) {
throw new RuntimeException("Unable to find defaultInstance in " + messageClassName, e);
} catch (SecurityException e) {
throw new RuntimeException("Unable to call defaultInstance in " + messageClassName, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Unable to call parsePartialFrom", e);
} catch (InvalidProtocolBufferException e) {
throw new RuntimeException("Unable to understand proto buffer", e);
}
}
private Class<?> resolveMessageClass() throws ClassNotFoundException { private Class<?> resolveMessageClass() throws ClassNotFoundException {
return messageClass != null ? messageClass : Class.forName(messageClassName); return messageClass != null ? messageClass : Class.forName(messageClassName);
} }

@ -2459,11 +2459,7 @@ public abstract class GeneratedMessageV3 extends AbstractMessage implements Seri
final String containingOneofCamelCaseName) { final String containingOneofCamelCaseName) {
isOneofField = isOneofField =
descriptor.getRealContainingOneof() != null; descriptor.getRealContainingOneof() != null;
hasHasMethod = hasHasMethod = descriptor.hasPresence();
descriptor.getFile().getSyntax() == FileDescriptor.Syntax.EDITIONS && descriptor.hasPresence()
|| descriptor.getFile().getSyntax() == FileDescriptor.Syntax.PROTO2
|| descriptor.hasOptionalKeyword()
|| (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE);
ReflectionInvoker reflectionInvoker = ReflectionInvoker reflectionInvoker =
new ReflectionInvoker( new ReflectionInvoker(
descriptor, descriptor,

@ -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
package com.google.protobuf;
import java.util.logging.Logger;
/**
* Provides the version of this Protobuf Java runtime, and methods for Protobuf Java gencode to
* validate that versions are compatible. Fields and methods in this class should be only accessed
* by related unit tests and Protobuf Java gencode, and should not be used elsewhere.
*/
public final class RuntimeVersion {
/** Indicates the domain of the Protobuf artifact. */
public enum RuntimeDomain {
GOOGLE_INTERNAL,
PUBLIC,
}
// The version of this runtime.
// Automatically updated by Protobuf release process. Do not edit manually.
public static final RuntimeDomain DOMAIN = RuntimeDomain.PUBLIC;
public static final int MAJOR = 3;
public static final int MINOR = 26;
public static final int PATCH = 0;
public static final String SUFFIX = "-dev";
private static final String VERSION_STRING = versionString(MAJOR, MINOR, PATCH, SUFFIX);
/**
* Validates that the gencode is in the same domain as the runtime.
*
* <p>This method will be directly called by the google-internal gencode to verify no cross-domain
* usages.
*
* @param gencodeDomain the domain where Protobuf Java code was generated.
* @throws ProtobufRuntimeVersionException if gencodeDomain is not the same as DOMAIN.
*/
public static void validateProtobufGencodeDomain(RuntimeDomain gencodeDomain) {
// 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");
if ((disableFlag != null && disableFlag.equals("true"))) {
return;
}
if (gencodeDomain != DOMAIN) {
throw new ProtobufRuntimeVersionException(
String.format(
"Mismatched Protobuf Gencode/Runtime domains: gencode %s, runtime %s. Cross-domain"
+ " usage of Protobuf is not supported.",
gencodeDomain, DOMAIN));
}
}
/**
* Validates that the gencode version is compatible with this runtime version according to
* https://protobuf.dev/support/cross-version-runtime-guarantee/.
*
* <p>This method is currently only used by Protobuf Java gencode in OSS.
*
* <p>This method is only for Protobuf Java gencode; do not call it elsewhere.
*
* @param domain the domain where Protobuf Java code was generated.
* @param major the major version of Protobuf Java gencode.
* @param minor the minor version of Protobuf Java gencode.
* @param patch the micro/patch version of Protobuf Java gencode.
* @param suffix the version suffix e.g. "-rc2", "-dev", etc.
* @throws ProtobufRuntimeVersionException if versions are incompatible.
*/
public static void validateProtobufGencodeVersion(
RuntimeDomain domain, int major, int minor, int patch, String suffix) {
// Check that version numbers are valid.
if (major < 0 || minor < 0 || patch < 0) {
throw new ProtobufRuntimeVersionException(
"Invalid gencode version: " + versionString(major, minor, patch, suffix));
}
validateProtobufGencodeDomain(domain);
String gencodeVersionString = versionString(major, minor, patch, suffix);
// Check that runtime major version is the same as the gencode major version.
if (major != MAJOR) {
throw new ProtobufRuntimeVersionException(
String.format(
"Mismatched Protobuf Gencode/Runtime major versions: gencode %s, runtime %s. Same"
+ " major version is required.",
gencodeVersionString, VERSION_STRING));
}
// Check that runtime version is newer than the gencode version.
if (MINOR < minor || (MINOR == minor && PATCH < patch)) {
throw new ProtobufRuntimeVersionException(
String.format(
"Protobuf Java runtime version cannot be older than the gencode version:"
+ "gencode %s, runtime %s.",
gencodeVersionString, VERSION_STRING));
}
// Check that runtime version suffix is the same as the gencode version suffix.
if (!suffix.equals(SUFFIX)) {
throw new ProtobufRuntimeVersionException(
String.format(
"Mismatched Protobuf Gencode/Runtime version suffixes: gencode %s, runtime %s."
+ " Version suffixes must be the same.",
gencodeVersionString, VERSION_STRING));
}
}
/**
* A runtime exception to be thrown by the version validator if version is not well defined or
* versions mismatch.
*/
public static final class ProtobufRuntimeVersionException extends RuntimeException {
public ProtobufRuntimeVersionException(String message) {
super(message);
}
}
/** Gets the version string given the version segments. */
private static String versionString(int major, int minor, int patch, String suffix) {
return String.format("%d.%d.%d%s", major, minor, patch, suffix);
}
}

@ -38,58 +38,6 @@ public final class TextFormat {
private static final String DEBUG_STRING_SILENT_MARKER = "\t "; private static final String DEBUG_STRING_SILENT_MARKER = "\t ";
/**
* Outputs a textual representation of the Protocol Message supplied into the parameter output.
* (This representation is the new version of the classic "ProtocolPrinter" output from the
* original Protocol Buffer system)
*
* @deprecated Use {@code printer().print(MessageOrBuilder, Appendable)}
*/
@Deprecated
@InlineMe(
replacement = "TextFormat.printer().print(message, output)",
imports = "com.google.protobuf.TextFormat")
public static void print(final MessageOrBuilder message, final Appendable output)
throws IOException {
printer().print(message, output);
}
/**
* Outputs a textual representation of {@code fields} to {@code output}.
*
* @deprecated Use {@code printer().print(UnknownFieldSet, Appendable)}
*/
@Deprecated
public static void print(final UnknownFieldSet fields, final Appendable output)
throws IOException {
printer().print(fields, output);
}
/**
* Same as {@code print()}, except that non-ASCII characters are not escaped.
*
* @deprecated Use {@code printer().escapingNonAscii(false).print(MessageOrBuilder, Appendable)}
*/
@Deprecated
@InlineMe(
replacement = "TextFormat.printer().escapingNonAscii(false).print(message, output)",
imports = "com.google.protobuf.TextFormat")
public static void printUnicode(final MessageOrBuilder message, final Appendable output)
throws IOException {
printer().escapingNonAscii(false).print(message, output);
}
/**
* Same as {@code print()}, except that non-ASCII characters are not escaped.
*
* @deprecated Use {@code printer().escapingNonAscii(false).print(UnknownFieldSet, Appendable)}
*/
@Deprecated
public static void printUnicode(final UnknownFieldSet fields, final Appendable output)
throws IOException {
printer().escapingNonAscii(false).print(fields, output);
}
/** /**
* Generates a human readable form of this message, useful for debugging and other purposes, with * 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 * no newline characters. This is just a trivial wrapper around {@link
@ -99,130 +47,6 @@ public final class TextFormat {
return printer().shortDebugString(message); return printer().shortDebugString(message);
} }
/**
* Generates a human readable form of the field, useful for debugging and other purposes, with
* no newline characters.
*
* @deprecated Use {@code printer().shortDebugString(FieldDescriptor, Object)}
*/
@Deprecated
public static String shortDebugString(final FieldDescriptor field, final Object value) {
return printer().shortDebugString(field, value);
}
/**
* Generates a human readable form of the unknown fields, useful for debugging and other
* purposes, with no newline characters.
*
* @deprecated Use {@code printer().shortDebugString(UnknownFieldSet)}
*/
@Deprecated
public static String shortDebugString(final UnknownFieldSet fields) {
return printer().shortDebugString(fields);
}
/**
* Like {@code print()}, but writes directly to a {@code String} and returns it.
*
* @deprecated Use {@code message.toString()}
*/
@Deprecated
@InlineMe(
replacement = "TextFormat.printer().printToString(message)",
imports = "com.google.protobuf.TextFormat")
public static String printToString(final MessageOrBuilder message) {
return printer().printToString(message);
}
/**
* Like {@code print()}, but writes directly to a {@code String} and returns it.
*
* @deprecated Use {@link UnknownFieldSet#toString()}
*/
@Deprecated
public static String printToString(final UnknownFieldSet fields) {
return printer().printToString(fields);
}
/**
* Same as {@code printToString()}, except that non-ASCII characters in string type fields are not
* escaped in backslash+octals.
*
* @deprecated Use {@code printer().escapingNonAscii(false).printToString(MessageOrBuilder)}
*/
@Deprecated
@InlineMe(
replacement = "TextFormat.printer().escapingNonAscii(false).printToString(message)",
imports = "com.google.protobuf.TextFormat")
public static String printToUnicodeString(final MessageOrBuilder message) {
return printer().escapingNonAscii(false).printToString(message);
}
/**
* Same as {@code printToString()}, except that non-ASCII characters in string type fields are
* not escaped in backslash+octals.
*
* @deprecated Use {@code printer().escapingNonAscii(false).printToString(UnknownFieldSet)}
*/
@Deprecated
public static String printToUnicodeString(final UnknownFieldSet fields) {
return printer().escapingNonAscii(false).printToString(fields);
}
/** @deprecated Use {@code printer().printField(FieldDescriptor, Object, Appendable)} */
@Deprecated
public static void printField(
final FieldDescriptor field, final Object value, final Appendable output)
throws IOException {
printer().printField(field, value, output);
}
/** @deprecated Use {@code printer().printFieldToString(FieldDescriptor, Object)} */
@Deprecated
public static String printFieldToString(final FieldDescriptor field, final Object value) {
return printer().printFieldToString(field, value);
}
/**
* Outputs a unicode textual representation of the value of given field value.
*
* <p>Same as {@code printFieldValue()}, except that non-ASCII characters in string type fields
* are not escaped in backslash+octals.
*
* @deprecated Use {@code printer().escapingNonAscii(false).printFieldValue(FieldDescriptor,
* Object, Appendable)}
* @param field the descriptor of the field
* @param value the value of the field
* @param output the output to which to append the formatted value
* @throws ClassCastException if the value is not appropriate for the given field descriptor
* @throws IOException if there is an exception writing to the output
*/
@Deprecated
public static void printUnicodeFieldValue(
final FieldDescriptor field, final Object value, final Appendable output)
throws IOException {
printer().escapingNonAscii(false).printFieldValue(field, value, output);
}
/**
* Outputs a textual representation of the value of given field value.
*
* @deprecated Use {@code printer().printFieldValue(FieldDescriptor, Object, Appendable)}
* @param field the descriptor of the field
* @param value the value of the field
* @param output the output to which to append the formatted value
* @throws ClassCastException if the value is not appropriate for the given field descriptor
* @throws IOException if there is an exception writing to the output
*/
@Deprecated
@InlineMe(
replacement = "TextFormat.printer().printFieldValue(field, value, output)",
imports = "com.google.protobuf.TextFormat")
public static void printFieldValue(
final FieldDescriptor field, final Object value, final Appendable output) throws IOException {
printer().printFieldValue(field, value, output);
}
/** /**
* Outputs a textual representation of the value of an unknown field. * Outputs a textual representation of the value of an unknown field.
* *
@ -283,16 +107,23 @@ public final class TextFormat {
public static final class Printer { public static final class Printer {
// Printer instance which escapes non-ASCII characters. // Printer instance which escapes non-ASCII characters.
private static final Printer DEFAULT = new Printer(true, TypeRegistry.getEmptyTypeRegistry()); private static final Printer DEFAULT =
new Printer(
true, TypeRegistry.getEmptyTypeRegistry(), ExtensionRegistryLite.getEmptyRegistry());
/** Whether to escape non ASCII characters with backslash and octal. */ /** Whether to escape non ASCII characters with backslash and octal. */
private final boolean escapeNonAscii; private final boolean escapeNonAscii;
private final TypeRegistry typeRegistry; private final TypeRegistry typeRegistry;
private final ExtensionRegistryLite extensionRegistry;
private Printer(boolean escapeNonAscii, TypeRegistry typeRegistry) { private Printer(
boolean escapeNonAscii,
TypeRegistry typeRegistry,
ExtensionRegistryLite extensionRegistry) {
this.escapeNonAscii = escapeNonAscii; this.escapeNonAscii = escapeNonAscii;
this.typeRegistry = typeRegistry; this.typeRegistry = typeRegistry;
this.extensionRegistry = extensionRegistry;
} }
/** /**
@ -305,7 +136,7 @@ public final class TextFormat {
* with the escape mode set to the given parameter. * with the escape mode set to the given parameter.
*/ */
public Printer escapingNonAscii(boolean escapeNonAscii) { public Printer escapingNonAscii(boolean escapeNonAscii) {
return new Printer(escapeNonAscii, typeRegistry); return new Printer(escapeNonAscii, typeRegistry, extensionRegistry);
} }
/** /**
@ -318,7 +149,20 @@ public final class TextFormat {
if (this.typeRegistry != TypeRegistry.getEmptyTypeRegistry()) { if (this.typeRegistry != TypeRegistry.getEmptyTypeRegistry()) {
throw new IllegalArgumentException("Only one typeRegistry is allowed."); throw new IllegalArgumentException("Only one typeRegistry is allowed.");
} }
return new Printer(escapeNonAscii, typeRegistry); return new Printer(escapeNonAscii, typeRegistry, extensionRegistry);
}
/**
* Creates a new {@link Printer} using the given extensionRegistry. The new Printer clones all
* other configurations from the current {@link Printer}.
*
* @throws IllegalArgumentException if a registry is already set.
*/
public Printer usingExtensionRegistry(ExtensionRegistryLite extensionRegistry) {
if (this.extensionRegistry != ExtensionRegistryLite.getEmptyRegistry()) {
throw new IllegalArgumentException("Only one extensionRegistry is allowed.");
}
return new Printer(escapeNonAscii, typeRegistry, extensionRegistry);
} }
/** /**
@ -377,7 +221,7 @@ public final class TextFormat {
return false; return false;
} }
contentBuilder = DynamicMessage.getDefaultInstance(contentType).newBuilderForType(); contentBuilder = DynamicMessage.getDefaultInstance(contentType).newBuilderForType();
contentBuilder.mergeFrom((ByteString) value); contentBuilder.mergeFrom((ByteString) value, extensionRegistry);
} catch (InvalidProtocolBufferException e) { } catch (InvalidProtocolBufferException e) {
// The value of Any is malformed. We cannot print it out nicely, so fallback to printing out // The value of Any is malformed. We cannot print it out nicely, so fallback to printing out
// the type_url and value as bytes. Note that we fail open here to be consistent with // the type_url and value as bytes. Note that we fail open here to be consistent with

@ -0,0 +1,162 @@
// 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 static com.google.common.truth.Truth.assertThat;
import protobuf_unittest.UnittestMset.RawMessageSet;
import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
import protobuf_unittest.UnittestMset.TestMessageSetExtension3;
import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Tests related to handling of MessageSets with lazily parsed extensions. */
@RunWith(JUnit4.class)
public class LazilyParsedMessageSetTest {
private static final int TYPE_ID_1 =
TestMessageSetExtension1.getDescriptor().getExtensions().get(0).getNumber();
private static final int TYPE_ID_2 =
TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber();
private static final int TYPE_ID_3 =
TestMessageSetExtension3.getDescriptor().getExtensions().get(0).getNumber();
private static final ByteString CORRUPTED_MESSAGE_PAYLOAD =
ByteString.copyFrom(new byte[] {(byte) 0xff});
@Before
public void setUp() {
ExtensionRegistryLite.setEagerlyParseMessageSets(false);
}
@Test
public void testParseAndUpdateMessageSet_unaccessedLazyFieldsAreNotLoaded() throws Exception {
ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
extensionRegistry.add(TestMessageSetExtension3.messageSetExtension);
// Set up a TestMessageSet with 2 extensions. The first extension has corrupted payload
// data. The test below makes sure that we never load this extension. If we ever do, then we
// will handle the exception and replace the value with the default empty message (this behavior
// is tested below in testLoadCorruptedLazyField_getsReplacedWithEmptyMessage). Later on we
// check that when we serialize the message set, we still have corrupted payload for the first
// extension.
RawMessageSet inputRaw =
RawMessageSet.newBuilder()
.addItem(
RawMessageSet.Item.newBuilder()
.setTypeId(TYPE_ID_1)
.setMessage(CORRUPTED_MESSAGE_PAYLOAD))
.addItem(
RawMessageSet.Item.newBuilder()
.setTypeId(TYPE_ID_2)
.setMessage(
TestMessageSetExtension2.newBuilder().setStr("foo").build().toByteString()))
.build();
ByteString inputData = inputRaw.toByteString();
// Re-parse as a TestMessageSet, so that all extensions are lazy
TestMessageSet messageSet = TestMessageSet.parseFrom(inputData, extensionRegistry);
// Update one extension and add a new one.
TestMessageSet.Builder builder = messageSet.toBuilder();
builder.setExtension(
TestMessageSetExtension2.messageSetExtension,
TestMessageSetExtension2.newBuilder().setStr("bar").build());
// Call .build() in the middle of updating the builder. This triggers a codepath that we want to
// make sure preserves lazy fields.
TestMessageSet unusedIntermediateMessageSet = builder.build();
builder.setExtension(
TestMessageSetExtension3.messageSetExtension,
TestMessageSetExtension3.newBuilder().setRequiredInt(666).build());
TestMessageSet updatedMessageSet = builder.build();
// Check that hasExtension call does not load lazy fields.
assertThat(updatedMessageSet.hasExtension(TestMessageSetExtension1.messageSetExtension))
.isTrue();
// Serialize. The first extension should still be unloaded and will get serialized using the
// same corrupted byte array.
ByteString outputData = updatedMessageSet.toByteString();
// Re-parse as RawMessageSet
RawMessageSet actualRaw =
RawMessageSet.parseFrom(outputData, ExtensionRegistry.getEmptyRegistry());
RawMessageSet expectedRaw =
RawMessageSet.newBuilder()
.addItem(
RawMessageSet.Item.newBuilder()
.setTypeId(TYPE_ID_1)
// This is the important part -- we want to make sure that the payload of the
// 1st extensions is the same corrupted byte array. If we ever load the
// extension during our manipulations above, then we would have replaced it with
// the default empty message.
.setMessage(CORRUPTED_MESSAGE_PAYLOAD))
.addItem(
RawMessageSet.Item.newBuilder()
.setTypeId(TYPE_ID_2)
.setMessage(
TestMessageSetExtension2.newBuilder().setStr("bar").build().toByteString()))
.addItem(
RawMessageSet.Item.newBuilder()
.setTypeId(TYPE_ID_3)
.setMessage(
TestMessageSetExtension3.newBuilder()
.setRequiredInt(666)
.build()
.toByteString()))
.build();
assertThat(actualRaw).isEqualTo(expectedRaw);
}
@Test
public void testLoadCorruptedLazyField_getsReplacedWithEmptyMessage() 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();
// Re-parse as a TestMessageSet, so that all extensions are lazy
TestMessageSet messageSet = TestMessageSet.parseFrom(inputData, extensionRegistry);
assertThat(messageSet.getExtension(TestMessageSetExtension1.messageSetExtension))
.isEqualTo(TestMessageSetExtension1.getDefaultInstance());
// Serialize. The first extension should be serialized as an empty message.
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);
}
}

@ -0,0 +1,138 @@
// 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 static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public final class RuntimeVersionTest {
@Test
public void versionValidation_invalidVersionNumbers() {
RuntimeVersion.ProtobufRuntimeVersionException thrown =
assertThrows(
RuntimeVersion.ProtobufRuntimeVersionException.class,
() ->
RuntimeVersion.validateProtobufGencodeVersion(
RuntimeVersion.DOMAIN, 1, -2, -3, ""));
assertThat(thrown).hasMessageThat().contains("Invalid gencode version: 1.-2.-3");
}
@Test
public void versionValidation_crossDomainDisallowed() {
RuntimeVersion.RuntimeDomain gencodeDomain = RuntimeVersion.RuntimeDomain.GOOGLE_INTERNAL;
RuntimeVersion.ProtobufRuntimeVersionException thrown =
assertThrows(
RuntimeVersion.ProtobufRuntimeVersionException.class,
() -> RuntimeVersion.validateProtobufGencodeDomain(gencodeDomain));
assertThat(thrown).hasMessageThat().contains("Mismatched Protobuf Gencode/Runtime domains");
}
@Test
public void versionValidation_sameDomainAllowed() {
RuntimeVersion.RuntimeDomain gencodeDomain = RuntimeVersion.RuntimeDomain.PUBLIC;
RuntimeVersion.validateProtobufGencodeDomain(gencodeDomain);
}
@Test
public void versionValidation_mismatchingMajorDisallowed() {
int gencodeMajor = 1;
RuntimeVersion.ProtobufRuntimeVersionException thrown =
assertThrows(
RuntimeVersion.ProtobufRuntimeVersionException.class,
() ->
RuntimeVersion.validateProtobufGencodeVersion(
RuntimeVersion.DOMAIN,
gencodeMajor,
RuntimeVersion.MINOR,
RuntimeVersion.PATCH,
RuntimeVersion.SUFFIX));
assertThat(thrown)
.hasMessageThat()
.contains("Mismatched Protobuf Gencode/Runtime major versions");
}
@Test
public void versionValidation_versionNumbersAllTheSameAllowed() {
RuntimeVersion.validateProtobufGencodeVersion(
RuntimeVersion.DOMAIN,
RuntimeVersion.MAJOR,
RuntimeVersion.MINOR,
RuntimeVersion.PATCH,
RuntimeVersion.SUFFIX);
}
@Test
public void versionValidation_NewerRuntimeVersionAllowed() {
int gencodeMinor = RuntimeVersion.MINOR - 1;
RuntimeVersion.validateProtobufGencodeVersion(
RuntimeVersion.DOMAIN,
RuntimeVersion.MAJOR,
gencodeMinor,
RuntimeVersion.PATCH,
RuntimeVersion.SUFFIX);
}
@Test
public void versionValidation_OlderRuntimeVersionDisallowed() {
int gencodeMinor = RuntimeVersion.MINOR + 1;
RuntimeVersion.ProtobufRuntimeVersionException thrown =
assertThrows(
RuntimeVersion.ProtobufRuntimeVersionException.class,
() ->
RuntimeVersion.validateProtobufGencodeVersion(
RuntimeVersion.DOMAIN,
RuntimeVersion.MAJOR,
gencodeMinor,
RuntimeVersion.PATCH,
RuntimeVersion.SUFFIX));
assertThat(thrown)
.hasMessageThat()
.contains("Protobuf Java runtime version cannot be older than the gencode version");
int gencodePatch = RuntimeVersion.PATCH + 1;
thrown =
assertThrows(
RuntimeVersion.ProtobufRuntimeVersionException.class,
() ->
RuntimeVersion.validateProtobufGencodeVersion(
RuntimeVersion.DOMAIN,
RuntimeVersion.MAJOR,
RuntimeVersion.MINOR,
gencodePatch,
RuntimeVersion.SUFFIX));
assertThat(thrown)
.hasMessageThat()
.contains("Protobuf Java runtime version cannot be older than the gencode version");
}
@Test
public void versionValidation_differentVesionSuffixDisallowed() {
String gencodeSuffix = "-test";
RuntimeVersion.ProtobufRuntimeVersionException thrown =
assertThrows(
RuntimeVersion.ProtobufRuntimeVersionException.class,
() ->
RuntimeVersion.validateProtobufGencodeVersion(
RuntimeVersion.DOMAIN,
RuntimeVersion.MAJOR,
RuntimeVersion.MINOR,
RuntimeVersion.PATCH,
gencodeSuffix));
assertThat(thrown)
.hasMessageThat()
.contains("Mismatched Protobuf Gencode/Runtime version suffixes");
}
}

@ -11,6 +11,7 @@ import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage; import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.protobuf.TestUtil.TEST_REQUIRED_INITIALIZED; import static com.google.protobuf.TestUtil.TEST_REQUIRED_INITIALIZED;
import static com.google.protobuf.TestUtil.TEST_REQUIRED_UNINITIALIZED; import static com.google.protobuf.TestUtil.TEST_REQUIRED_UNINITIALIZED;
import static protobuf_unittest.UnittestProto.optionalInt32Extension;
import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertThrows;
import com.google.protobuf.DescriptorProtos.DescriptorProto; import com.google.protobuf.DescriptorProtos.DescriptorProto;
@ -623,6 +624,83 @@ public class TextFormatTest {
assertThat(actual).isEqualTo(expected); assertThat(actual).isEqualTo(expected);
} }
@Test
public void testPrintAny_anyWithDynamicMessageContainingExtensionTreatedAsUnknown()
throws Exception {
Descriptor descriptor =
createDescriptorForAny(
FieldDescriptorProto.newBuilder()
.setName("type_url")
.setNumber(1)
.setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
.setType(FieldDescriptorProto.Type.TYPE_STRING)
.build(),
FieldDescriptorProto.newBuilder()
.setName("value")
.setNumber(2)
.setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
.setType(FieldDescriptorProto.Type.TYPE_BYTES)
.build());
DynamicMessage testAny =
DynamicMessage.newBuilder(descriptor)
.setField(
descriptor.findFieldByNumber(1),
"type.googleapis.com/" + TestAllExtensions.getDescriptor().getFullName())
.setField(
descriptor.findFieldByNumber(2),
TestAllExtensions.newBuilder()
.setExtension(optionalInt32Extension, 12345)
.build()
.toByteString())
.build();
String actual =
TextFormat.printer()
.usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build())
.printToString(testAny);
String expected = "[type.googleapis.com/protobuf_unittest.TestAllExtensions] {\n 1: 12345\n}\n";
assertThat(actual).isEqualTo(expected);
}
@Test
public void testPrintAny_anyWithDynamicMessageContainingExtensionWithRegistry() throws Exception {
Descriptor descriptor =
createDescriptorForAny(
FieldDescriptorProto.newBuilder()
.setName("type_url")
.setNumber(1)
.setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
.setType(FieldDescriptorProto.Type.TYPE_STRING)
.build(),
FieldDescriptorProto.newBuilder()
.setName("value")
.setNumber(2)
.setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
.setType(FieldDescriptorProto.Type.TYPE_BYTES)
.build());
DynamicMessage testAny =
DynamicMessage.newBuilder(descriptor)
.setField(
descriptor.findFieldByNumber(1),
"type.googleapis.com/" + TestAllExtensions.getDescriptor().getFullName())
.setField(
descriptor.findFieldByNumber(2),
TestAllExtensions.newBuilder()
.setExtension(optionalInt32Extension, 12345)
.build()
.toByteString())
.build();
String actual =
TextFormat.printer()
.usingTypeRegistry(TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build())
.usingExtensionRegistry(TestUtil.getFullExtensionRegistry())
.printToString(testAny);
String expected =
"[type.googleapis.com/protobuf_unittest.TestAllExtensions] {\n"
+ " [protobuf_unittest.optional_int32_extension]: 12345\n"
+ "}\n";
assertThat(actual).isEqualTo(expected);
}
@Test @Test
public void testPrintAny_anyFromWithNoValueField() throws Exception { public void testPrintAny_anyFromWithNoValueField() throws Exception {
Descriptor descriptor = Descriptor descriptor =

@ -25,6 +25,7 @@ import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.util.List; import java.util.List;
import org.junit.After;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.JUnit4; import org.junit.runners.JUnit4;
@ -39,6 +40,13 @@ public class WireFormatTest {
TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber(); TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber();
private static final int UNKNOWN_TYPE_ID = 1550055; private static final int UNKNOWN_TYPE_ID = 1550055;
@After
public void tearDown() {
// Whether to parse message sets eagerly is stored in a global static. Since some tests modify
// the value, make sure to reset it between test runs.
ExtensionRegistryLite.setEagerlyParseMessageSets(false);
}
@Test @Test
public void testSerialization() throws Exception { public void testSerialization() throws Exception {
TestAllTypes message = TestUtil.getAllSet(); TestAllTypes message = TestUtil.getAllSet();

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.google.protobuf</groupId> <groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId> <artifactId>protobuf-parent</artifactId>
<version>3.24.0</version> <version>3.25.0</version>
</parent> </parent>
<artifactId>protobuf-kotlin-lite</artifactId> <artifactId>protobuf-kotlin-lite</artifactId>

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.google.protobuf</groupId> <groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId> <artifactId>protobuf-parent</artifactId>
<version>3.24.0</version> <version>3.25.0</version>
</parent> </parent>
<artifactId>protobuf-kotlin</artifactId> <artifactId>protobuf-kotlin</artifactId>

@ -29,7 +29,7 @@ protobuf Java Lite runtime. If you are using Maven, include the following:
<dependency> <dependency>
<groupId>com.google.protobuf</groupId> <groupId>com.google.protobuf</groupId>
<artifactId>protobuf-javalite</artifactId> <artifactId>protobuf-javalite</artifactId>
<version>3.24.0</version> <version>3.25.0</version>
</dependency> </dependency>
``` ```

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.google.protobuf</groupId> <groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId> <artifactId>protobuf-parent</artifactId>
<version>3.24.0</version> <version>3.25.0</version>
</parent> </parent>
<artifactId>protobuf-javalite</artifactId> <artifactId>protobuf-javalite</artifactId>
@ -161,6 +161,7 @@
<include>RawMessageInfo.java</include> <include>RawMessageInfo.java</include>
<include>Reader.java</include> <include>Reader.java</include>
<include>RopeByteString.java</include> <include>RopeByteString.java</include>
<include>RuntimeVersion.java</include>
<include>Schema.java</include> <include>Schema.java</include>
<include>SchemaFactory.java</include> <include>SchemaFactory.java</include>
<include>SchemaUtil.java</include> <include>SchemaUtil.java</include>
@ -224,6 +225,7 @@
<exclude>Proto2SchemaTest.java</exclude> <exclude>Proto2SchemaTest.java</exclude>
<exclude>Proto2UnknownEnumValueTest.java</exclude> <exclude>Proto2UnknownEnumValueTest.java</exclude>
<exclude>RepeatedFieldBuilderV3Test.java</exclude> <exclude>RepeatedFieldBuilderV3Test.java</exclude>
<exclude>RuntimeVersionTest.java</exclude>
<exclude>ServiceTest.java</exclude> <exclude>ServiceTest.java</exclude>
<exclude>SingleFieldBuilderV3Test.java</exclude> <exclude>SingleFieldBuilderV3Test.java</exclude>
<exclude>TestBadIdentifiers.java</exclude> <exclude>TestBadIdentifiers.java</exclude>

@ -55,6 +55,11 @@ public final class OsgiWrapper implements Callable<Integer> {
description = "The classpath that contains dependencies of the input jar, separated with :") description = "The classpath that contains dependencies of the input jar, separated with :")
private String classpath; private String classpath;
@Option(
names = {"--automatic_module_name"},
description = "The automatic module name of the bundle")
private String automaticModuleName;
@Option( @Option(
names = {"--bundle_copyright"}, names = {"--bundle_copyright"},
description = "Copyright string for the bundle") description = "Copyright string for the bundle")
@ -106,6 +111,7 @@ public final class OsgiWrapper implements Callable<Integer> {
Analyzer analyzer = new Analyzer(); Analyzer analyzer = new Analyzer();
analyzer.setJar(bin); analyzer.setJar(bin);
analyzer.setProperty(Analyzer.AUTOMATIC_MODULE_NAME, automaticModuleName);
analyzer.setProperty(Analyzer.BUNDLE_NAME, bundleName); analyzer.setProperty(Analyzer.BUNDLE_NAME, bundleName);
analyzer.setProperty(Analyzer.BUNDLE_SYMBOLICNAME, bundleSymbolicName); analyzer.setProperty(Analyzer.BUNDLE_SYMBOLICNAME, bundleSymbolicName);
analyzer.setProperty(Analyzer.BUNDLE_VERSION, bundleVersion); analyzer.setProperty(Analyzer.BUNDLE_VERSION, bundleVersion);

@ -23,6 +23,7 @@ load("@rules_java//java:defs.bzl", "java_library")
# which is probably sub-optimal. # which is probably sub-optimal.
def osgi_java_library( def osgi_java_library(
name, name,
automatic_module_name,
bundle_description, bundle_description,
bundle_doc_url, bundle_doc_url,
bundle_license, bundle_license,
@ -119,6 +120,7 @@ def osgi_java_library(
# Repackage the jar with an OSGI manifest # Repackage the jar with an OSGI manifest
_osgi_jar( _osgi_jar(
name = name, name = name,
automatic_module_name = automatic_module_name,
bundle_description = bundle_description, bundle_description = bundle_description,
bundle_doc_url = bundle_doc_url, bundle_doc_url = bundle_doc_url,
bundle_license = bundle_license, bundle_license = bundle_license,
@ -141,6 +143,7 @@ def _run_osgi_wrapper(ctx, input_jar, classpath_jars, output_jar):
args.add_joined("--classpath", classpath_jars, join_with = ":") args.add_joined("--classpath", classpath_jars, join_with = ":")
args.add("--input_jar", input_jar.path) args.add("--input_jar", input_jar.path)
args.add("--output_jar", output_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_copyright", ctx.attr.bundle_copyright)
args.add("--bundle_description", ctx.attr.bundle_description) args.add("--bundle_description", ctx.attr.bundle_description)
args.add("--bundle_doc_url", ctx.attr.bundle_doc_url) args.add("--bundle_doc_url", ctx.attr.bundle_doc_url)
@ -215,6 +218,7 @@ _osgi_jar = rule(
"output_jar": "lib%{name}.jar", "output_jar": "lib%{name}.jar",
}, },
attrs = { attrs = {
"automatic_module_name": attr.string(),
"bundle_copyright": attr.string(), "bundle_copyright": attr.string(),
"bundle_description": attr.string(), "bundle_description": attr.string(),
"bundle_doc_url": attr.string(), "bundle_doc_url": attr.string(),

@ -4,7 +4,7 @@
<groupId>com.google.protobuf</groupId> <groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId> <artifactId>protobuf-parent</artifactId>
<version>3.24.0</version> <version>3.25.0</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>Protocol Buffers [Parent]</name> <name>Protocol Buffers [Parent]</name>

@ -8,7 +8,7 @@
</parent> </parent>
<groupId>com.google.protobuf</groupId> <groupId>com.google.protobuf</groupId>
<artifactId>protoc</artifactId> <artifactId>protoc</artifactId>
<version>3.24.0</version> <version>3.25.0</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>Protobuf Compiler</name> <name>Protobuf Compiler</name>
<description> <description>

@ -26,6 +26,7 @@ protobuf_versioned_java_library(
srcs = glob([ srcs = glob([
"src/main/java/com/google/protobuf/util/*.java", "src/main/java/com/google/protobuf/util/*.java",
]), ]),
automatic_module_name = "com.google.protobuf.util",
bundle_description = "Utilities for Protocol Buffers", bundle_description = "Utilities for Protocol Buffers",
bundle_name = "Protocol Buffers [Util]", bundle_name = "Protocol Buffers [Util]",
bundle_symbolic_name = "com.google.protobuf.util", bundle_symbolic_name = "com.google.protobuf.util",

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.google.protobuf</groupId> <groupId>com.google.protobuf</groupId>
<artifactId>protobuf-parent</artifactId> <artifactId>protobuf-parent</artifactId>
<version>3.24.0</version> <version>3.25.0</version>
</parent> </parent>
<artifactId>protobuf-java-util</artifactId> <artifactId>protobuf-java-util</artifactId>

@ -1,32 +1,9 @@
// Protocol Buffers - Google's data interchange format // Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved. // Copyright 2023 Google LLC. All rights reserved.
// https://developers.google.com/protocol-buffers/
// //
// Redistribution and use in source and binary forms, with or without // Use of this source code is governed by a BSD-style
// modification, are permitted provided that the following conditions are // license that can be found in the LICENSE file or at
// met: // https://developers.google.com/open-source/licenses/bsd
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, 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.
#include "upb/reflection/def.h" #include "upb/reflection/def.h"

@ -1,4 +1,4 @@
# Copyright (c) 2009-2021, Google LLC # Copyright (c) 2023, Google LLC
# All rights reserved. # All rights reserved.
# #
# Use of this source code is governed by a BSD-style # Use of this source code is governed by a BSD-style

@ -1,32 +1,9 @@
// Protocol Buffers - Google's data interchange format // Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved. // Copyright 2023 Google LLC. All rights reserved.
// https://developers.google.com/protocol-buffers/
// //
// Redistribution and use in source and binary forms, with or without // Use of this source code is governed by a BSD-style
// modification, are permitted provided that the following conditions are // license that can be found in the LICENSE file or at
// met: // https://developers.google.com/open-source/licenses/bsd
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, 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.
#include <lauxlib.h> #include <lauxlib.h>
#include <lua.h> #include <lua.h>

@ -1,32 +1,9 @@
// Protocol Buffers - Google's data interchange format // Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved. // Copyright 2023 Google LLC. All rights reserved.
// https://developers.google.com/protocol-buffers/
// //
// Redistribution and use in source and binary forms, with or without // Use of this source code is governed by a BSD-style
// modification, are permitted provided that the following conditions are // license that can be found in the LICENSE file or at
// met: // https://developers.google.com/open-source/licenses/bsd
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, 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.
/* /*
* lupb_Message -- Message/Array/Map objects in Lua/C that wrap upb * lupb_Message -- Message/Array/Map objects in Lua/C that wrap upb

@ -1,39 +1,16 @@
// Protocol Buffers - Google's data interchange format /// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved. // Copyright 2023 Google LLC. All rights reserved.
// https://developers.google.com/protocol-buffers/
// //
// Redistribution and use in source and binary forms, with or without // Use of this source code is governed by a BSD-style
// modification, are permitted provided that the following conditions are // license that can be found in the LICENSE file or at
// met: // https://developers.google.com/open-source/licenses/bsd
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, 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.
syntax = "proto2"; syntax = "proto2";
import "google/protobuf/timestamp.proto";
package upb_lua_test; package upb_lua_test;
import "google/protobuf/timestamp.proto";
message MapTest { message MapTest {
map<string, double> map_string_double = 1; map<string, double> map_string_double = 1;
} }

@ -2,33 +2,10 @@
Protocol Buffers - Google's data interchange format Protocol Buffers - Google's data interchange format
Copyright 2023 Google LLC. All rights reserved. Copyright 2023 Google LLC. All rights reserved.
https://developers.google.com/protocol-buffers/
Use of this source code is governed by a BSD-style
Redistribution and use in source and binary forms, with or without license that can be found in the LICENSE file or at
modification, are permitted provided that the following conditions are https://developers.google.com/open-source/licenses/bsd
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, 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.
--]]-------------------------------------------------------------------------- --]]--------------------------------------------------------------------------

@ -1,32 +1,9 @@
// Protocol Buffers - Google's data interchange format // Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved. // Copyright 2023 Google LLC. All rights reserved.
// https://developers.google.com/protocol-buffers/
// //
// Redistribution and use in source and binary forms, with or without // Use of this source code is governed by a BSD-style
// modification, are permitted provided that the following conditions are // license that can be found in the LICENSE file or at
// met: // https://developers.google.com/open-source/licenses/bsd
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, 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.
/* /*
* require("lua") -- A Lua extension for upb. * require("lua") -- A Lua extension for upb.

@ -1,32 +1,9 @@
// Protocol Buffers - Google's data interchange format // Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved. // Copyright 2023 Google LLC. All rights reserved.
// https://developers.google.com/protocol-buffers/
// //
// Redistribution and use in source and binary forms, with or without // Use of this source code is governed by a BSD-style
// modification, are permitted provided that the following conditions are // license that can be found in the LICENSE file or at
// met: // https://developers.google.com/open-source/licenses/bsd
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, 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.
/* /*
* Shared definitions for upb Lua modules. * Shared definitions for upb Lua modules.

@ -1,29 +1,11 @@
--[[-------------------------------------------------------------------------- --[[--------------------------------------------------------------------------
Copyright (c) 2009-2021, Google LLC Protocol Buffers - Google's data interchange format
All rights reserved. Copyright 2023 Google LLC. All rights reserved.
Redistribution and use in source and binary forms, with or without Use of this source code is governed by a BSD-style
modification, are permitted provided that the following conditions are met: license that can be found in the LICENSE file or at
* Redistributions of source code must retain the above copyright https://developers.google.com/open-source/licenses/bsd
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Google LLC nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--]]-------------------------------------------------------------------------- --]]--------------------------------------------------------------------------

@ -1,32 +1,9 @@
// Protocol Buffers - Google's data interchange format // Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved. // Copyright 2023 Google LLC. All rights reserved.
// https://developers.google.com/protocol-buffers/
// //
// Redistribution and use in source and binary forms, with or without // Use of this source code is governed by a BSD-style
// modification, are permitted provided that the following conditions are // license that can be found in the LICENSE file or at
// met: // https://developers.google.com/open-source/licenses/bsd
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, 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.
#include "google/protobuf/descriptor.pb.h" #include "google/protobuf/descriptor.pb.h"
#include "absl/strings/str_replace.h" #include "absl/strings/str_replace.h"

@ -160,6 +160,7 @@ objc_library(
conformance_test( conformance_test(
name = "conformance_test", name = "conformance_test",
failure_list = "//conformance:failure_list_objc.txt", failure_list = "//conformance:failure_list_objc.txt",
maximum_edition = "2023",
target_compatible_with = ["@platforms//os:macos"], target_compatible_with = ["@platforms//os:macos"],
testee = "//conformance:conformance_objc", testee = "//conformance:conformance_objc",
) )

@ -168,6 +168,9 @@ GPB_FINAL @interface GPBAny : GPBMessage
/** Must be a valid serialized protocol buffer of the above specified type. */ /** Must be a valid serialized protocol buffer of the above specified type. */
@property(nonatomic, readwrite, copy, null_resettable) NSData *value; @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.
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -3,6 +3,7 @@
// source: google/protobuf/any.proto // source: google/protobuf/any.proto
#import "GPBProtocolBuffers_RuntimeSupport.h" #import "GPBProtocolBuffers_RuntimeSupport.h"
#import "GPBWellKnownTypes.h"
#import "GPBAny.pbobjc.h" #import "GPBAny.pbobjc.h"
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30007 #if GOOGLE_PROTOBUF_OBJC_VERSION < 30007
@ -39,6 +40,13 @@ static GPBFileDescription GPBAnyRoot_FileDescription = {
.syntax = GPBFileSyntaxProto3 .syntax = GPBFileSyntaxProto3
}; };
// This is to help make sure that the GPBWellKnownTypes.* categories get linked and
// developers do not have to use the `-ObjC` linker flag. More information
// here: https://medium.com/ios-os-x-development/categories-in-static-libraries-78e41f8ddb96
__attribute__((used)) static NSString* any_importCategories () {
return GPBWellKnownTypesErrorDomain;
}
#pragma mark - GPBAny #pragma mark - GPBAny
@implementation GPBAny @implementation GPBAny

@ -160,7 +160,14 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, int64_t value
} }
- (void)dealloc { - (void)dealloc {
[self flush]; @try {
[self flush];
} @catch (NSException *exception) {
// -dealloc methods cannot fail, so swallow any exceptions from flushing.
#if defined(DEBUG) && DEBUG
NSLog(@"GPBCodedOutputStream: Exception while flushing in dealloc: %@", exception);
#endif
}
[state_.output close]; [state_.output close];
[state_.output release]; [state_.output release];
[buffer_ release]; [buffer_ release];

@ -1044,6 +1044,7 @@ void GPBDictionaryReadEntry(id mapDictionary, GPBCodedInputStream *stream,
//% GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; //% GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
//% WriteDict##KEY_NAME##Field(outputStream, key->value##KEY_NAME, kMapKeyFieldNumber, keyDataType); //% WriteDict##KEY_NAME##Field(outputStream, key->value##KEY_NAME, kMapKeyFieldNumber, keyDataType);
//% WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); //% WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
//% [outputStream flush];
//% [outputStream release]; //% [outputStream release];
//% return data; //% return data;
//%} //%}
@ -2788,6 +2789,7 @@ void GPBDictionaryReadEntry(id mapDictionary, GPBCodedInputStream *stream,
GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
WriteDictUInt32Field(outputStream, key->valueUInt32, kMapKeyFieldNumber, keyDataType); WriteDictUInt32Field(outputStream, key->valueUInt32, kMapKeyFieldNumber, keyDataType);
WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
[outputStream flush];
[outputStream release]; [outputStream release];
return data; return data;
} }
@ -4518,6 +4520,7 @@ void GPBDictionaryReadEntry(id mapDictionary, GPBCodedInputStream *stream,
GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
WriteDictInt32Field(outputStream, key->valueInt32, kMapKeyFieldNumber, keyDataType); WriteDictInt32Field(outputStream, key->valueInt32, kMapKeyFieldNumber, keyDataType);
WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
[outputStream flush];
[outputStream release]; [outputStream release];
return data; return data;
} }
@ -6248,6 +6251,7 @@ void GPBDictionaryReadEntry(id mapDictionary, GPBCodedInputStream *stream,
GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
WriteDictUInt64Field(outputStream, key->valueUInt64, kMapKeyFieldNumber, keyDataType); WriteDictUInt64Field(outputStream, key->valueUInt64, kMapKeyFieldNumber, keyDataType);
WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
[outputStream flush];
[outputStream release]; [outputStream release];
return data; return data;
} }
@ -7978,6 +7982,7 @@ void GPBDictionaryReadEntry(id mapDictionary, GPBCodedInputStream *stream,
GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
WriteDictInt64Field(outputStream, key->valueInt64, kMapKeyFieldNumber, keyDataType); WriteDictInt64Field(outputStream, key->valueInt64, kMapKeyFieldNumber, keyDataType);
WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
[outputStream flush];
[outputStream release]; [outputStream release];
return data; return data;
} }
@ -9768,6 +9773,7 @@ void GPBDictionaryReadEntry(id mapDictionary, GPBCodedInputStream *stream,
GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
WriteDictStringField(outputStream, key->valueString, kMapKeyFieldNumber, keyDataType); WriteDictStringField(outputStream, key->valueString, kMapKeyFieldNumber, keyDataType);
WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
[outputStream flush];
[outputStream release]; [outputStream release];
return data; return data;
} }
@ -11741,6 +11747,7 @@ void GPBDictionaryReadEntry(id mapDictionary, GPBCodedInputStream *stream,
GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
WriteDictBoolField(outputStream, key->valueBool, kMapKeyFieldNumber, keyDataType); WriteDictBoolField(outputStream, key->valueBool, kMapKeyFieldNumber, keyDataType);
WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum);
[outputStream flush];
[outputStream release]; [outputStream release];
return data; return data;
} }

@ -123,6 +123,9 @@ GPB_FINAL @interface GPBDuration : GPBMessage
**/ **/
@property(nonatomic, readwrite) int32_t nanos; @property(nonatomic, readwrite) int32_t nanos;
// NOTE: There are some Objective-C specific methods/properties in
// GPBWellKnownTypes.h that will likey be useful.
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -3,6 +3,7 @@
// source: google/protobuf/duration.proto // source: google/protobuf/duration.proto
#import "GPBProtocolBuffers_RuntimeSupport.h" #import "GPBProtocolBuffers_RuntimeSupport.h"
#import "GPBWellKnownTypes.h"
#import "GPBDuration.pbobjc.h" #import "GPBDuration.pbobjc.h"
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30007 #if GOOGLE_PROTOBUF_OBJC_VERSION < 30007
@ -39,6 +40,13 @@ static GPBFileDescription GPBDurationRoot_FileDescription = {
.syntax = GPBFileSyntaxProto3 .syntax = GPBFileSyntaxProto3
}; };
// This is to help make sure that the GPBWellKnownTypes.* categories get linked and
// developers do not have to use the `-ObjC` linker flag. More information
// here: https://medium.com/ios-os-x-development/categories-in-static-libraries-78e41f8ddb96
__attribute__((used)) static NSString* duration_importCategories () {
return GPBWellKnownTypesErrorDomain;
}
#pragma mark - GPBDuration #pragma mark - GPBDuration
@implementation GPBDuration @implementation GPBDuration

@ -1343,6 +1343,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithData:data]; GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithData:data];
@try { @try {
[self writeToCodedOutputStream:stream]; [self writeToCodedOutputStream:stream];
[stream flush];
} @catch (NSException *exception) { } @catch (NSException *exception) {
// This really shouldn't happen. Normally, this could mean there was a bug in the library and it // This really shouldn't happen. Normally, this could mean there was a bug in the library and it
// failed to match between computing the size and writing out the bytes. However, the more // failed to match between computing the size and writing out the bytes. However, the more
@ -1369,6 +1370,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithData:data]; GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithData:data];
@try { @try {
[self writeDelimitedToCodedOutputStream:stream]; [self writeDelimitedToCodedOutputStream:stream];
[stream flush];
} @catch (NSException *exception) { } @catch (NSException *exception) {
// This really shouldn't happen. Normally, this could mean there was a bug in the library and it // This really shouldn't happen. Normally, this could mean there was a bug in the library and it
// failed to match between computing the size and writing out the bytes. However, the more // failed to match between computing the size and writing out the bytes. However, the more
@ -1380,8 +1382,9 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
NSLog(@"%@: Internal exception while building message delimitedData: %@", [self class], NSLog(@"%@: Internal exception while building message delimitedData: %@", [self class],
exception); exception);
#endif #endif
// If it happens, truncate. // If it happens, return an empty data.
data.length = 0; [stream release];
return [NSData data];
} }
[stream release]; [stream release];
return data; return data;
@ -1391,6 +1394,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithOutputStream:output]; GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithOutputStream:output];
@try { @try {
[self writeToCodedOutputStream:stream]; [self writeToCodedOutputStream:stream];
[stream flush];
size_t bytesWritten = [stream bytesWritten]; size_t bytesWritten = [stream bytesWritten];
if (bytesWritten > kMaximumMessageSize) { if (bytesWritten > kMaximumMessageSize) {
[NSException raise:GPBMessageExceptionMessageTooLarge [NSException raise:GPBMessageExceptionMessageTooLarge
@ -1434,6 +1438,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
GPBCodedOutputStream *codedOutput = [[GPBCodedOutputStream alloc] initWithOutputStream:output]; GPBCodedOutputStream *codedOutput = [[GPBCodedOutputStream alloc] initWithOutputStream:output];
@try { @try {
[self writeDelimitedToCodedOutputStream:codedOutput]; [self writeDelimitedToCodedOutputStream:codedOutput];
[codedOutput flush];
} @finally { } @finally {
[codedOutput release]; [codedOutput release];
} }

@ -152,6 +152,9 @@ GPB_FINAL @interface GPBTimestamp : GPBMessage
**/ **/
@property(nonatomic, readwrite) int32_t nanos; @property(nonatomic, readwrite) int32_t nanos;
// NOTE: There are some Objective-C specific methods/properties in
// GPBWellKnownTypes.h that will likey be useful.
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -3,6 +3,7 @@
// source: google/protobuf/timestamp.proto // source: google/protobuf/timestamp.proto
#import "GPBProtocolBuffers_RuntimeSupport.h" #import "GPBProtocolBuffers_RuntimeSupport.h"
#import "GPBWellKnownTypes.h"
#import "GPBTimestamp.pbobjc.h" #import "GPBTimestamp.pbobjc.h"
#if GOOGLE_PROTOBUF_OBJC_VERSION < 30007 #if GOOGLE_PROTOBUF_OBJC_VERSION < 30007
@ -39,6 +40,13 @@ static GPBFileDescription GPBTimestampRoot_FileDescription = {
.syntax = GPBFileSyntaxProto3 .syntax = GPBFileSyntaxProto3
}; };
// This is to help make sure that the GPBWellKnownTypes.* categories get linked and
// developers do not have to use the `-ObjC` linker flag. More information
// here: https://medium.com/ios-os-x-development/categories-in-static-libraries-78e41f8ddb96
__attribute__((used)) static NSString* timestamp_importCategories () {
return GPBWellKnownTypesErrorDomain;
}
#pragma mark - GPBTimestamp #pragma mark - GPBTimestamp
@implementation GPBTimestamp @implementation GPBTimestamp

@ -207,6 +207,7 @@ static void GPBUnknownFieldSetSerializedSizeAsMessageSet(__unused const void *ke
NSMutableData *data = [NSMutableData dataWithLength:self.serializedSize]; NSMutableData *data = [NSMutableData dataWithLength:self.serializedSize];
GPBCodedOutputStream *output = [[GPBCodedOutputStream alloc] initWithData:data]; GPBCodedOutputStream *output = [[GPBCodedOutputStream alloc] initWithData:data];
[self writeToCodedOutputStream:output]; [self writeToCodedOutputStream:output];
[output flush];
[output release]; [output release];
return data; return data;
} }

@ -201,6 +201,24 @@ typedef NS_ENUM(NSInteger, GPBWellKnownTypesErrorCode) {
*/ */
- (nullable GPBMessage *)unpackMessageClass:(Class)messageClass error:(NSError **)errorPtr; - (nullable GPBMessage *)unpackMessageClass:(Class)messageClass error:(NSError **)errorPtr;
/**
* Unpacks the serialized message as if it was an instance of the given class.
*
* @note When checking type_url, the base URL is not checked, only the fully
* qualified name.
*
* @param messageClass The class to use to deserialize the contained message.
* @param extensionRegistry The extension registry to use to look up extensions.
* @param errorPtr Pointer to an error that will be populated if something
* goes wrong.
*
* @return An instance of the given class populated with the contained data, or
* nil on failure.
*/
- (nullable GPBMessage *)unpackMessageClass:(Class)messageClass
extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry
error:(NSError **)errorPtr;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -195,6 +195,12 @@ static NSString *ParseTypeFromURL(NSString *typeURLString) {
} }
- (GPBMessage *)unpackMessageClass:(Class)messageClass error:(NSError **)errorPtr { - (GPBMessage *)unpackMessageClass:(Class)messageClass error:(NSError **)errorPtr {
return [self unpackMessageClass:messageClass extensionRegistry:nil error:errorPtr];
}
- (nullable GPBMessage *)unpackMessageClass:(Class)messageClass
extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry
error:(NSError **)errorPtr {
NSString *fullName = [messageClass descriptor].fullName; NSString *fullName = [messageClass descriptor].fullName;
if (fullName.length == 0) { if (fullName.length == 0) {
if (errorPtr) { if (errorPtr) {
@ -215,10 +221,7 @@ static NSString *ParseTypeFromURL(NSString *typeURLString) {
return nil; return nil;
} }
// Any is proto3, which means no extensions, so this assumes anything put return [messageClass parseFromData:self.value extensionRegistry:extensionRegistry error:errorPtr];
// within an any also won't need extensions. A second helper could be added
// if needed.
return [messageClass parseFromData:self.value error:errorPtr];
} }
@end @end

@ -393,4 +393,27 @@
NSException, GPBCodedOutputStreamException_WriteFailed); NSException, GPBCodedOutputStreamException_WriteFailed);
} }
- (void)testThatDeallocNeverThrows {
uint8_t buffer[1] = {0};
// Output stream which can write precisely 1 byte of data before it's full.
NSOutputStream* output = [[[NSOutputStream alloc] initToBuffer:buffer
capacity:sizeof(buffer)] autorelease];
NSMutableData* outputBuffer = [NSMutableData data];
GPBCodedOutputStream* codedOutput =
[[GPBCodedOutputStream alloc] initWithOutputStream:output data:outputBuffer];
[codedOutput writeRawByte:0x23];
[codedOutput flush];
// Put one more byte in the output buffer.
[codedOutput writeRawByte:0x42];
XCTAssertThrowsSpecificNamed([codedOutput flush], NSException,
GPBCodedOutputStreamException_WriteFailed);
// -dealloc must not throw when it flushes, even if a previous flush failed.
XCTAssertNoThrow([codedOutput release]);
}
@end @end

@ -2225,4 +2225,17 @@
XCTAssertNil(shouldGetAPrefixMessage); XCTAssertNil(shouldGetAPrefixMessage);
} }
- (void)testWriteToFullOutputStreamShouldThrow {
uint8_t buffer[1] = {0};
// Output stream which can write precisely 1 byte of data before it's full.
NSOutputStream *output = [[[NSOutputStream alloc] initToBuffer:buffer
capacity:sizeof(buffer)] autorelease];
TestAllTypes *message = [TestAllTypes message];
[message setOptionalInt32:1];
XCTAssertThrowsSpecificNamed([message writeToOutputStream:output], NSException,
GPBCodedOutputStreamException_WriteFailed);
}
@end @end

@ -4,10 +4,10 @@
load("@rules_pkg//:mappings.bzl", "pkg_filegroup", "pkg_files", "strip_prefix") load("@rules_pkg//:mappings.bzl", "pkg_filegroup", "pkg_files", "strip_prefix")
load("@rules_pkg//:pkg.bzl", "pkg_tar") load("@rules_pkg//:pkg.bzl", "pkg_tar")
load("//upb/cmake:build_defs.bzl", "staleness_test") load("//:protobuf_version.bzl", "PROTOBUF_PHP_VERSION", "PROTOC_VERSION")
load("//build_defs:internal_shell.bzl", "inline_sh_binary") load("//build_defs:internal_shell.bzl", "inline_sh_binary")
load("//conformance:defs.bzl", "conformance_test") load("//conformance:defs.bzl", "conformance_test")
load("//:protobuf_version.bzl", "PROTOBUF_PHP_VERSION", "PROTOC_VERSION") load("//upb/cmake:build_defs.bzl", "staleness_test")
filegroup( filegroup(
name = "source_files", name = "source_files",
@ -32,7 +32,7 @@ inline_sh_binary(
name = "build_extension", name = "build_extension",
cmd = """ cmd = """
mkdir -p php/ext/google/protobuf/third_party/utf8_range mkdir -p php/ext/google/protobuf/third_party/utf8_range
cp external/utf8_range/* php/ext/google/protobuf/third_party/utf8_range cp third_party/utf8_range/* php/ext/google/protobuf/third_party/utf8_range
pushd php/ext/google/protobuf pushd php/ext/google/protobuf
phpize phpize
@ -46,7 +46,7 @@ genrule(
name = "extension", name = "extension",
srcs = [ srcs = [
":source_files", ":source_files",
"@utf8_range//:utf8_range_srcs", "//third_party/utf8_range:utf8_range_srcs",
], ],
outs = ["protobuf.so"], outs = ["protobuf.so"],
cmd = """ cmd = """
@ -157,8 +157,8 @@ pkg_files(
pkg_files( pkg_files(
name = "utf8_range_files", name = "utf8_range_files",
srcs = [ srcs = [
"@utf8_range//:LICENSE", "//third_party/utf8_range:LICENSE",
"@utf8_range//:utf8_range_srcs", "//third_party/utf8_range:utf8_range_srcs",
], ],
prefix = "third_party/utf8_range", prefix = "third_party/utf8_range",
) )

@ -400,11 +400,8 @@ static zval* Message_get_property_ptr_ptr(zend_object* object,
static zend_object* Message_clone_obj(zend_object* object) { static zend_object* Message_clone_obj(zend_object* object) {
Message* intern = (Message*)object; Message* intern = (Message*)object;
const upb_MiniTable* t = upb_MessageDef_MiniTable(intern->desc->msgdef); const upb_MiniTable* t = upb_MessageDef_MiniTable(intern->desc->msgdef);
upb_Message* clone = upb_Message_New(t, Arena_Get(&intern->arena)); upb_Message* clone =
upb_Message_ShallowClone(intern->msg, t, Arena_Get(&intern->arena));
// TODO: copy unknown fields?
// TODO: use official upb msg copy function
memcpy(clone, intern->msg, t->size);
zval ret; zval ret;
Message_GetPhpWrapper(&ret, intern->desc, clone, &intern->arena); Message_GetPhpWrapper(&ret, intern->desc, clone, &intern->arena);
return Z_OBJ_P(&ret); return Z_OBJ_P(&ret);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save