diff --git a/.github/BUILD.bazel b/.github/BUILD.bazel index 6d619f02ef..45297fc116 100644 --- a/.github/BUILD.bazel +++ b/.github/BUILD.bazel @@ -4,9 +4,25 @@ # When updating, also ensure the "xcode_destination" entries in # `.github/workflows/test_objectivec.yml` are supported for the given versions # of Xcode. +xcode_version( + name = "version15_2_15C500b", + aliases = [ + "15C500b", + "15.2", + ], + default_ios_sdk_version = "17.2", + default_macos_sdk_version = "14.2", + default_tvos_sdk_version = "17.2", + default_watchos_sdk_version = "10.2", + version = "15.2.0.15C500b", +) + xcode_version( name = "version14_2_14C18", - aliases = ["14C18"], + aliases = [ + "14C18", + "14.2", + ], default_ios_sdk_version = "16.2", default_macos_sdk_version = "13.1", default_tvos_sdk_version = "16.1", @@ -16,7 +32,10 @@ xcode_version( xcode_version( name = "version14_1_0_14B47b", - aliases = ["14B47b"], + aliases = [ + "14B47b", + "14.1", + ], default_ios_sdk_version = "16.1", default_macos_sdk_version = "13.0", default_tvos_sdk_version = "16.1", @@ -28,6 +47,7 @@ xcode_config( name = "host_xcodes", default = ":version14_2_14C18", versions = [ + ":version15_2_15C500b", ":version14_2_14C18", ":version14_1_0_14B47b", ], diff --git a/.github/workflows/test_cpp.yml b/.github/workflows/test_cpp.yml index 275010610a..b18bc344af 100644 --- a/.github/workflows/test_cpp.yml +++ b/.github/workflows/test_cpp.yml @@ -19,9 +19,9 @@ jobs: config: - { name: Optimized, flags: --config=opt } - { name: Debug, flags: --config=dbg } - - { name: ASAN, flags: --config=asan, runner: ubuntu-22-large } - - { name: MSAN, flags: --config=docker-msan, runner: ubuntu-22-large } - - { name: TSAN, flags: --config=tsan } + - { name: ASAN, flags: --config=asan, runner: ubuntu-20-large } + - { name: MSAN, flags: --config=docker-msan, runner: ubuntu-20-large } + - { name: TSAN, flags: --config=tsan, runner: ubuntu-20-large } - { name: UBSAN, flags: --config=ubsan } - { name: No-RTTI, flags: --cxxopt=-fno-rtti } include: @@ -108,7 +108,9 @@ jobs: command: > -c "set -ex; sccache -z; - cmake . -DWITH_PROTOC=/workspace/${{ steps.cross-compile.outputs.protoc }} -Dprotobuf_BUILD_CONFORMANCE=ON -DCMAKE_CXX_STANDARD=14 -Dprotobuf_WITH_ZLIB=OFF ${{ env.SCCACHE_CMAKE_FLAGS }}; + cmake . -DWITH_PROTOC=/workspace/${{ steps.cross-compile.outputs.protoc }} + -Dprotobuf_BUILD_LIBUPB=OFF -Dprotobuf_BUILD_CONFORMANCE=ON -DCMAKE_CXX_STANDARD=14 + -Dprotobuf_WITH_ZLIB=OFF ${{ env.SCCACHE_CMAKE_FLAGS }}; cmake --build . --parallel 20; ctest --parallel 20; sccache -s" @@ -151,7 +153,7 @@ jobs: command: >- /test.sh ${{ matrix.flags}} ${{ env.SCCACHE_CMAKE_FLAGS }} -Dprotobuf_BUILD_TESTS=ON -Dprotobuf_USE_EXTERNAL_GTEST=ON - -Dprotobuf_ABSL_PROVIDER=package -Dprotobuf_BUILD_LIBUPB=ON + -Dprotobuf_ABSL_PROVIDER=package linux-cmake-install: name: Linux CMake Install @@ -175,7 +177,9 @@ jobs: image: us-docker.pkg.dev/protobuf-build/containers/test/linux/cmake:3.13.3-63dd26c0c7a808d92673a3e52e848189d4ab0f17 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} command: >- - /install.sh -DCMAKE_CXX_STANDARD=14 ${{ env.SCCACHE_CMAKE_FLAGS }} -Dprotobuf_USE_EXTERNAL_GTEST=ON -Dprotobuf_ABSL_PROVIDER=package -Dprotobuf_BUILD_SHARED_LIBS=ON \&\& + /install.sh -DCMAKE_CXX_STANDARD=14 ${{ env.SCCACHE_CMAKE_FLAGS }} + -Dprotobuf_USE_EXTERNAL_GTEST=ON -Dprotobuf_ABSL_PROVIDER=package + -Dprotobuf_BUILD_SHARED_LIBS=ON \&\& /test.sh ${{ env.SCCACHE_CMAKE_FLAGS }} -Dprotobuf_REMOVE_INSTALLED_HEADERS=ON @@ -250,7 +254,7 @@ jobs: -c 'set -ex; cd /workspace; sccache -z; - cmake . -Dprotobuf_BUILD_LIBUPB=ON ${{ matrix.flags }} ${{ env.SCCACHE_CMAKE_FLAGS }}; + cmake . ${{ matrix.flags }} ${{ env.SCCACHE_CMAKE_FLAGS }}; cmake --build . --parallel 20; ctest --verbose --parallel 20; sccache -s' @@ -278,7 +282,7 @@ jobs: credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} command: >- /test.sh ${{ env.SCCACHE_CMAKE_FLAGS }} - -Dprotobuf_BUILD_CONFORMANCE=ON -Dprotobuf_BUILD_EXAMPLES=ON -DCMAKE_CXX_STANDARD=14 -Dprotobuf_BUILD_LIBUPB=ON + -Dprotobuf_BUILD_CONFORMANCE=ON -Dprotobuf_BUILD_EXAMPLES=ON -DCMAKE_CXX_STANDARD=14 linux-cmake-32-bit: name: Linux CMake 32-bit @@ -306,7 +310,7 @@ jobs: /bin/bash -cex ' cd /workspace; sccache -z; - cmake . -DCMAKE_CXX_STANDARD=14 -Dprotobuf_BUILD_LIBUPB=ON ${{ env.SCCACHE_CMAKE_FLAGS }}; + cmake . -DCMAKE_CXX_STANDARD=14 ${{ env.SCCACHE_CMAKE_FLAGS }}; cmake --build . --parallel 20; ctest --verbose --parallel 20; sccache -s' @@ -370,7 +374,7 @@ jobs: flags: >- -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF - -Dprotobuf_BUILD_EXAMPLES=ON -Dprotobuf_BUILD_LIBUPB=ON + -Dprotobuf_BUILD_EXAMPLES=ON vsversion: '2022' cache-prefix: windows-2022-cmake - name: Windows CMake 2019 @@ -378,7 +382,7 @@ jobs: flags: >- -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF - -Dprotobuf_BUILD_EXAMPLES=ON -Dprotobuf_BUILD_LIBUPB=ON + -Dprotobuf_BUILD_EXAMPLES=ON vsversion: '2019' cache-prefix: windows-2019-cmake # windows-2019 has python3.7 installed, which is incompatible with the latest gcloud @@ -386,14 +390,14 @@ jobs: - name: Windows CMake 32-bit os: windows-2022 flags: >- - -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -Dprotobuf_BUILD_LIBUPB=ON + -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF vsversion: '2022' windows-arch: 'win32' cache-prefix: windows-2022-win32-cmake - name: Windows CMake Shared os: windows-2022 flags: >- - -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -Dprotobuf_BUILD_LIBUPB=ON + -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -Dprotobuf_BUILD_SHARED_LIBS=ON vsversion: '2022' cache-prefix: windows-2022-cmake diff --git a/.github/workflows/test_objectivec.yml b/.github/workflows/test_objectivec.yml index 8e96a02308..31175c1abe 100644 --- a/.github/workflows/test_objectivec.yml +++ b/.github/workflows/test_objectivec.yml @@ -70,20 +70,25 @@ jobs: matrix: PLATFORM: ["ios", "macos", "tvos", "watchos"] CONFIGURATION: ["Debug", "Release"] - name: CocoaPods ${{ matrix.PLATFORM}} ${{ matrix.CONFIGURATION}} - runs-on: macos-12 - env: - DEVELOPER_DIR: /Applications/Xcode_14.1.app/Contents/Developer + include: + - OS: macos-12 + XCODE: "14.1" + name: CocoaPods ${{ matrix.PLATFORM }} ${{ matrix.CONFIGURATION }} + runs-on: ${{ matrix.OS }} steps: - name: Checkout pending changes uses: protocolbuffers/protobuf-ci/checkout@v2 with: ref: ${{ inputs.safe-checkout }} + - name: Xcode version + run: sudo xcode-select -switch /Applications/Xcode_${{ matrix.XCODE }}.app - name: Pod lib lint - uses: protocolbuffers/protobuf-ci/bash@v2 + uses: protocolbuffers/protobuf-ci/bazel@v2 with: credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} - command: | + bazel-cache: cocoapods/${{ matrix.XCODE }} + bash: | + ./regenerate_stale_files.sh $BAZEL_FLAGS --xcode_version="${{ matrix.XCODE }}" pod lib lint --verbose \ --configuration=${{ matrix.CONFIGURATION }} \ --platforms=${{ matrix.PLATFORM }} \ diff --git a/.github/workflows/test_upb.yml b/.github/workflows/test_upb.yml index cb85456448..3c257356fc 100644 --- a/.github/workflows/test_upb.yml +++ b/.github/workflows/test_upb.yml @@ -20,14 +20,14 @@ jobs: - { name: "Bazel 7", bazel_version: "7.0.0" } - { name: "Fastbuild" } - { name: "Optimized", flags: "-c opt" } - - { name: "ASAN", flags: "--config=asan -c dbg", exclude-targets: "-//benchmarks:benchmark -//python/..." } + - { name: "ASAN", flags: "--config=asan -c dbg", exclude-targets: "-//benchmarks:benchmark -//python/...", runner: ubuntu-20-large } - { name: "UBSAN", flags: "--config=ubsan -c dbg", exclude-targets: "-//benchmarks:benchmark -//python/... -//lua/..." } - { name: "32-bit", flags: "--copt=-m32 --linkopt=-m32", exclude-targets: "-//benchmarks:benchmark -//python/..." } # TODO: Add 32-bit ASAN test # TODO: Restore the FastTable tests name: ${{ matrix.config.name }} - runs-on: ubuntu-latest + runs-on: ${{ matrix.config.runner || 'ubuntu-latest' }} steps: - name: Checkout pending changes diff --git a/.gitignore b/.gitignore index f25b4f7cdf..37d7aebc74 100644 --- a/.gitignore +++ b/.gitignore @@ -173,6 +173,7 @@ ruby/tests/test_import_pb.rb ruby/tests/test_ruby_package_pb.rb ruby/tests/generated_code_proto2_pb.rb ruby/tests/multi_level_nesting_test_pb.rb +ruby/tests/service_test_pb.rb ruby/tests/test_import_proto2_pb.rb ruby/tests/test_ruby_package_proto2_pb.rb ruby/compatibility_tests/v3.0.0/protoc diff --git a/CMakeLists.txt b/CMakeLists.txt index eaed1fe9cf..4169fa1d22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,7 @@ option(protobuf_BUILD_EXAMPLES "Build examples" OFF) option(protobuf_BUILD_PROTOBUF_BINARIES "Build protobuf libraries and protoc compiler" ON) option(protobuf_BUILD_PROTOC_BINARIES "Build libprotoc and protoc compiler" ON) option(protobuf_BUILD_LIBPROTOC "Build libprotoc" OFF) -option(protobuf_BUILD_LIBUPB "Build libupb" OFF) +option(protobuf_BUILD_LIBUPB "Build libupb" ON) option(protobuf_DISABLE_RTTI "Remove runtime type information in the binaries" OFF) option(protobuf_TEST_XML_OUTDIR "Output directory for XML logs from tests." "") option(protobuf_ALLOW_CCACHE "Adjust build flags to allow for ccache support." OFF) @@ -316,10 +316,10 @@ if (protobuf_BUILD_PROTOBUF_BINARIES) endif () if (protobuf_BUILD_LIBUPB) include(${protobuf_SOURCE_DIR}/cmake/libupb.cmake) - include(${protobuf_SOURCE_DIR}/cmake/upb_generators.cmake) if (NOT DEFINED protobuf_LIB_UPB) set(protobuf_LIB_UPB libupb) endif () + include(${protobuf_SOURCE_DIR}/cmake/upb_generators.cmake) endif () if (protobuf_BUILD_PROTOC_BINARIES) include(${protobuf_SOURCE_DIR}/cmake/protoc.cmake) @@ -334,6 +334,7 @@ else () set(protobuf_LIB_PROTOC protobuf::libprotoc) set(protobuf_LIB_PROTOBUF protobuf::libprotobuf) set(protobuf_LIB_PROTOBUF_LITE protobuf::libprotobuf-lite) + set(protobuf_LIB_UPB protobuf::libupb) message(STATUS "CMake installation of Protobuf found.") endif () endif () diff --git a/WORKSPACE b/WORKSPACE index e4ae60df0f..b4c7ac68ce 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -153,9 +153,9 @@ http_archive( http_archive( name = "com_google_googleapis", - urls = ["https://github.com/googleapis/googleapis/archive/30ed2662a85403cbdeb9ea38df1e414a2a276b83.zip"], - strip_prefix = "googleapis-30ed2662a85403cbdeb9ea38df1e414a2a276b83", - sha256 = "4dfc28101127d22abd6f0f6308d915d490c4594c0cfcf7643769c446d6763a46", + urls = ["https://github.com/googleapis/googleapis/archive/d81d0b9e6993d6ab425dff4d7c3d05fb2e59fa57.zip"], + strip_prefix = "googleapis-d81d0b9e6993d6ab425dff4d7c3d05fb2e59fa57", + sha256 = "d986023c3d8d2e1b161e9361366669cac9fb97c2a07e656c2548aca389248bb4", build_file = "//benchmarks:BUILD.googleapis", patch_cmds = ["find google -type f -name BUILD.bazel -delete"], ) diff --git a/bazel/amalgamate.py b/bazel/amalgamate.py index 8dc14cbb52..f4e83fc79a 100755 --- a/bazel/amalgamate.py +++ b/bazel/amalgamate.py @@ -54,7 +54,7 @@ class Amalgamator: self.output_c.write('#include "%s"\n' % (self.h_out)) if self.h_out == "ruby-upb.h": self.output_h.write("// Ruby is still using proto3 enum semantics for proto2\n") - self.output_h.write("#define UPB_DISABLE_PROTO2_ENUM_CHECKING\n") + self.output_h.write("#define UPB_DISABLE_CLOSED_ENUM_CHECKING\n") self.output_h.write("/* Amalgamated source file */\n") diff --git a/bazel/py_proto_library.bzl b/bazel/py_proto_library.bzl index 41c4f6c2ba..f7328ca3c1 100644 --- a/bazel/py_proto_library.bzl +++ b/bazel/py_proto_library.bzl @@ -128,7 +128,6 @@ _py_proto_library_aspect = aspect( ) py_proto_library = rule( - output_to_genfiles = True, implementation = _py_proto_library_rule_impl, attrs = { "deps": attr.label_list( diff --git a/bazel/upb_c_proto_library.bzl b/bazel/upb_c_proto_library.bzl index 108582e5cb..b5bc22edc1 100644 --- a/bazel/upb_c_proto_library.bzl +++ b/bazel/upb_c_proto_library.bzl @@ -57,7 +57,6 @@ def _upb_c_proto_library_rule_impl(ctx): return upb_proto_rule_impl(ctx, UpbWrappedCcInfo, _UpbWrappedGeneratedSrcsInfo) upb_c_proto_library = rule( - output_to_genfiles = True, implementation = _upb_c_proto_library_rule_impl, attrs = { "deps": attr.label_list( diff --git a/bazel/upb_minitable_proto_library.bzl b/bazel/upb_minitable_proto_library.bzl index c00d824145..11a48a1467 100644 --- a/bazel/upb_minitable_proto_library.bzl +++ b/bazel/upb_minitable_proto_library.bzl @@ -65,7 +65,6 @@ def _upb_minitable_proto_library_rule_impl(ctx): return upb_proto_rule_impl(ctx, UpbMinitableCcInfo, _UpbWrappedGeneratedSrcsInfo) upb_minitable_proto_library = rule( - output_to_genfiles = True, implementation = _upb_minitable_proto_library_rule_impl, attrs = { "deps": attr.label_list( diff --git a/bazel/upb_proto_reflection_library.bzl b/bazel/upb_proto_reflection_library.bzl index 4181f7b650..c61fce0f7d 100644 --- a/bazel/upb_proto_reflection_library.bzl +++ b/bazel/upb_proto_reflection_library.bzl @@ -55,7 +55,6 @@ def _upb_proto_reflection_library_rule_impl(ctx): return upb_proto_rule_impl(ctx, _UpbDefsWrappedCcInfo, _WrappedDefsGeneratedSrcsInfo) upb_proto_reflection_library = rule( - output_to_genfiles = True, implementation = _upb_proto_reflection_library_rule_impl, attrs = { "deps": attr.label_list( diff --git a/benchmarks/BUILD.googleapis b/benchmarks/BUILD.googleapis index 446967898c..0587de74db 100644 --- a/benchmarks/BUILD.googleapis +++ b/benchmarks/BUILD.googleapis @@ -36,7 +36,7 @@ load( proto_library( name = "ads_proto", srcs = glob([ - "google/ads/googleads/v13/**/*.proto", + "google/ads/googleads/v16/**/*.proto", "google/api/**/*.proto", "google/rpc/**/*.proto", "google/longrunning/**/*.proto", diff --git a/benchmarks/benchmark.cc b/benchmarks/benchmark.cc index 47efbcd8b7..e499b29ead 100644 --- a/benchmarks/benchmark.cc +++ b/benchmarks/benchmark.cc @@ -14,7 +14,7 @@ #include #include -#include "google/ads/googleads/v13/services/google_ads_service.upbdefs.h" +#include "google/ads/googleads/v16/services/google_ads_service.upbdefs.h" #include "google/protobuf/descriptor.pb.h" #include "absl/container/flat_hash_set.h" #include "absl/log/absl_check.h" @@ -181,14 +181,14 @@ static void BM_LoadAdsDescriptor_Upb(benchmark::State& state) { for (auto _ : state) { upb::DefPool defpool; if (Mode == NoLayout) { - google_ads_googleads_v13_services_SearchGoogleAdsRequest_getmsgdef( + google_ads_googleads_v16_services_SearchGoogleAdsRequest_getmsgdef( defpool.ptr()); bytes_per_iter = _upb_DefPool_BytesLoaded(defpool.ptr()); } else { bytes_per_iter = 0; LoadDefInit_BuildLayout( defpool.ptr(), - &google_ads_googleads_v13_services_google_ads_service_proto_upbdefinit, + &google_ads_googleads_v16_services_google_ads_service_proto_upbdefinit, &bytes_per_iter); } } @@ -200,11 +200,11 @@ BENCHMARK_TEMPLATE(BM_LoadAdsDescriptor_Upb, WithLayout); template static void BM_LoadAdsDescriptor_Proto2(benchmark::State& state) { extern _upb_DefPool_Init - google_ads_googleads_v13_services_google_ads_service_proto_upbdefinit; + google_ads_googleads_v16_services_google_ads_service_proto_upbdefinit; std::vector serialized_files; absl::flat_hash_set seen_files; CollectFileDescriptors( - &google_ads_googleads_v13_services_google_ads_service_proto_upbdefinit, + &google_ads_googleads_v16_services_google_ads_service_proto_upbdefinit, serialized_files, seen_files); size_t bytes_per_iter = 0; for (auto _ : state) { @@ -227,7 +227,7 @@ static void BM_LoadAdsDescriptor_Proto2(benchmark::State& state) { if (Mode == WithLayout) { protobuf::DynamicMessageFactory factory; const protobuf::Descriptor* d = pool.FindMessageTypeByName( - "google.ads.googleads.v13.services.SearchGoogleAdsResponse"); + "google.ads.googleads.v16.services.SearchGoogleAdsResponse"); if (!d) { printf("Failed to find descriptor.\n"); exit(1); diff --git a/build_defs/BUILD.bazel b/build_defs/BUILD.bazel index 3da64aa3b9..f1394e391e 100644 --- a/build_defs/BUILD.bazel +++ b/build_defs/BUILD.bazel @@ -35,10 +35,18 @@ config_setting( # For more info on the various crosstool_tops used by NDK Bazel builds, see: # https://docs.bazel.build/versions/master/android-ndk.html#configuring-the-stl +# When using https://bazel.build/concepts/platforms config_setting( name = "config_android", + constraint_values = ["@platforms//os:android"], +) + +# When using legacy flags like --android_crosstool_top, --android_cpu, and --fat_apk_cpu +config_setting( + name = "config_android-legacy-default-crosstool", values = { - "crosstool_top": "@platforms//os:android", + # Default of `--android_crosstool_top` + "crosstool_top": "//external:android/crosstool", }, ) diff --git a/build_defs/cpp_opts.bzl b/build_defs/cpp_opts.bzl index 09c8b79179..f667a40881 100644 --- a/build_defs/cpp_opts.bzl +++ b/build_defs/cpp_opts.bzl @@ -29,6 +29,7 @@ COPTS = select({ # Android and MSVC builds do not need to link in a separate pthread library. LINK_OPTS = select({ "//build_defs:config_android": [], + "//build_defs:config_android-legacy-default-crosstool": [], "//build_defs:config_android-stlport": [], "//build_defs:config_android-libcpp": [], "//build_defs:config_android-gnu-libstdcpp": [], diff --git a/cmake/conformance.cmake b/cmake/conformance.cmake index dd72d12343..b4c3a44f1b 100644 --- a/cmake/conformance.cmake +++ b/cmake/conformance.cmake @@ -12,11 +12,6 @@ elseif(protobuf_JSONCPP_PROVIDER STREQUAL "package") find_package(jsoncpp REQUIRED) endif() -set(protoc_cpp_args) -if (protobuf_BUILD_SHARED_LIBS) - set(protoc_cpp_args "dllexport_decl=PROTOBUF_TEST_EXPORTS:") -endif () - file(MAKE_DIRECTORY ${protobuf_BINARY_DIR}/conformance) add_custom_command( @@ -26,7 +21,7 @@ add_custom_command( DEPENDS ${protobuf_PROTOC_EXE} ${protobuf_SOURCE_DIR}/conformance/conformance.proto COMMAND ${protobuf_PROTOC_EXE} ${protobuf_SOURCE_DIR}/conformance/conformance.proto --proto_path=${protobuf_SOURCE_DIR}/conformance - --cpp_out=${protoc_cpp_args}${protobuf_BINARY_DIR}/conformance + --cpp_out=${protobuf_BINARY_DIR}/conformance ) file(MAKE_DIRECTORY ${protobuf_BINARY_DIR}/src) @@ -52,10 +47,10 @@ add_custom_command( ${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto3_editions.proto ${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto2_editions.proto --proto_path=${protobuf_SOURCE_DIR}/src - --cpp_out=${protoc_cpp_args}${protobuf_BINARY_DIR}/src + --cpp_out=${protobuf_BINARY_DIR}/src ) -add_library(libconformance_common ${protobuf_SHARED_OR_STATIC} +add_library(libconformance_common STATIC ${protobuf_BINARY_DIR}/conformance/conformance.pb.h ${protobuf_BINARY_DIR}/conformance/conformance.pb.cc ${protobuf_BINARY_DIR}/src/google/protobuf/test_messages_proto2.pb.h @@ -71,11 +66,6 @@ target_link_libraries(libconformance_common ${protobuf_LIB_PROTOBUF} ${protobuf_ABSL_USED_TARGETS} ) -if(protobuf_BUILD_SHARED_LIBS) - target_compile_definitions(libconformance_common - PUBLIC PROTOBUF_USE_DLLS - PRIVATE LIBPROTOBUF_TEST_EXPORTS) -endif() add_executable(conformance_test_runner ${protobuf_SOURCE_DIR}/conformance/binary_json_conformance_suite.cc diff --git a/cmake/install.cmake b/cmake/install.cmake index c822838d03..676d702363 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -29,12 +29,11 @@ set(_protobuf_libraries libprotobuf-lite libprotobuf) if (protobuf_BUILD_LIBPROTOC) list(APPEND _protobuf_libraries libprotoc) endif (protobuf_BUILD_LIBPROTOC) +if (protobuf_BUILD_LIBUPB) + list(APPEND _protobuf_libraries libupb) +endif () foreach(_library ${_protobuf_libraries}) - set_property(TARGET ${_library} - PROPERTY INTERFACE_INCLUDE_DIRECTORIES - $ - $) if (UNIX AND NOT APPLE) set_property(TARGET ${_library} PROPERTY INSTALL_RPATH "$ORIGIN") @@ -49,16 +48,27 @@ foreach(_library ${_protobuf_libraries}) endforeach() if (protobuf_BUILD_PROTOC_BINARIES) + set(_protobuf_binaries protoc) install(TARGETS protoc EXPORT protobuf-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc) - if (UNIX AND NOT APPLE) - set_property(TARGET protoc - PROPERTY INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") - elseif (APPLE) - set_property(TARGET protoc - PROPERTY INSTALL_RPATH "@loader_path/../lib") - endif() + if (protobuf_BUILD_LIBUPB) + foreach (generator upb upbdefs upb_minitable) + list(APPEND _protobuf_binaries protoc-gen-${generator}) + install(TARGETS protoc-gen-${generator} EXPORT protobuf-targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT upb-generators + BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT upb-generators) + endforeach () + endif () + foreach (binary IN LISTS _protobuf_binaries) + if (UNIX AND NOT APPLE) + set_property(TARGET ${binary} + PROPERTY INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") + elseif (APPLE) + set_property(TARGET ${binary} + PROPERTY INSTALL_RPATH "@loader_path/../lib") + endif () + endforeach () endif (protobuf_BUILD_PROTOC_BINARIES) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/protobuf.pc ${CMAKE_CURRENT_BINARY_DIR}/protobuf-lite.pc DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") @@ -73,6 +83,17 @@ set(protobuf_HEADERS ${plugin_proto_proto_srcs} ${java_features_proto_proto_srcs} ) +if (protobuf_BUILD_LIBUPB) + list(APPEND protobuf_HEADERS ${libupb_hdrs}) + # Manually install the bootstrap headers + install( + FILES + ${protobuf_SOURCE_DIR}/upb/reflection/cmake/google/protobuf/descriptor.upb.h + ${protobuf_SOURCE_DIR}/upb/reflection/cmake/google/protobuf/descriptor.upb_minitable.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/google/protobuf + COMPONENT protobuf-headers + ) +endif () foreach(_header ${protobuf_HEADERS}) string(FIND ${_header} "${protobuf_SOURCE_DIR}/src" _find_src) string(FIND ${_header} "${protobuf_SOURCE_DIR}" _find_nosrc) diff --git a/cmake/libprotobuf-lite.cmake b/cmake/libprotobuf-lite.cmake index f343458cf5..dfccbc8077 100644 --- a/cmake/libprotobuf-lite.cmake +++ b/cmake/libprotobuf-lite.cmake @@ -23,7 +23,10 @@ endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "Android") target_link_libraries(libprotobuf-lite PRIVATE log) endif() -target_include_directories(libprotobuf-lite PUBLIC ${protobuf_SOURCE_DIR}/src) +target_include_directories(libprotobuf-lite PUBLIC + $ + $ +) target_link_libraries(libprotobuf-lite PUBLIC ${protobuf_ABSL_USED_TARGETS}) protobuf_configure_target(libprotobuf-lite) if(protobuf_BUILD_SHARED_LIBS) diff --git a/cmake/libprotobuf.cmake b/cmake/libprotobuf.cmake index 422754a1ab..11c09b1bc0 100644 --- a/cmake/libprotobuf.cmake +++ b/cmake/libprotobuf.cmake @@ -26,7 +26,10 @@ endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "Android") target_link_libraries(libprotobuf PRIVATE log) endif() -target_include_directories(libprotobuf PUBLIC ${protobuf_SOURCE_DIR}/src) +target_include_directories(libprotobuf PUBLIC + $ + $ +) target_link_libraries(libprotobuf PUBLIC ${protobuf_ABSL_USED_TARGETS}) protobuf_configure_target(libprotobuf) if(protobuf_BUILD_SHARED_LIBS) diff --git a/cmake/libupb.cmake b/cmake/libupb.cmake index a9558463dc..7476e56eb7 100644 --- a/cmake/libupb.cmake +++ b/cmake/libupb.cmake @@ -20,7 +20,10 @@ add_library(libupb STATIC ${protobuf_version_rc_file} ) -target_include_directories(libupb PUBLIC ${bootstrap_cmake_dir}) +target_include_directories(libupb PUBLIC + $ + $ +) protobuf_configure_target(libupb) diff --git a/cmake/tests.cmake b/cmake/tests.cmake index 351aeb0d1f..64a0d00449 100644 --- a/cmake/tests.cmake +++ b/cmake/tests.cmake @@ -18,11 +18,6 @@ set(tests_protos ${util_test_protos_files} ) -set(protoc_cpp_args) -if (protobuf_BUILD_SHARED_LIBS) - set(protoc_cpp_args "dllexport_decl=PROTOBUF_TEST_EXPORTS") -endif () - file(MAKE_DIRECTORY ${protobuf_BINARY_DIR}/src) set(lite_test_proto_files) @@ -32,23 +27,17 @@ foreach(proto_file ${lite_test_protos}) LANGUAGE cpp OUT_VAR pb_generated_files IMPORT_DIRS ${protobuf_SOURCE_DIR}/src - PLUGIN_OPTIONS ${protoc_cpp_args} ) set(lite_test_proto_files ${lite_test_proto_files} ${pb_generated_files}) endforeach(proto_file) set(tests_proto_files) foreach(proto_file ${tests_protos}) - if (MSVC AND protobuf_BUILD_SHARED_LIBS AND ${proto_file} MATCHES ".*enormous.*") - # Our enormous protos are too big for windows DLLs. - continue() - endif () protobuf_generate( PROTOS ${proto_file} LANGUAGE cpp OUT_VAR pb_generated_files IMPORT_DIRS ${protobuf_SOURCE_DIR}/src - PLUGIN_OPTIONS ${protoc_cpp_args} ) set(tests_proto_files ${tests_proto_files} ${pb_generated_files}) endforeach(proto_file) @@ -96,7 +85,7 @@ else() set(protobuf_GTEST_ARGS) endif() -add_library(libtest_common ${protobuf_SHARED_OR_STATIC} +add_library(libtest_common STATIC ${tests_proto_files} ) target_link_libraries(libtest_common @@ -109,11 +98,6 @@ target_link_libraries(libtest_common if (MSVC) target_compile_options(libtest_common PRIVATE /bigobj) endif () -if(protobuf_BUILD_SHARED_LIBS) - target_compile_definitions(libtest_common - PUBLIC PROTOBUF_USE_DLLS - PRIVATE LIBPROTOBUF_TEST_EXPORTS) -endif() add_executable(tests ${tests_files} ${common_test_files}) if (MSVC) @@ -155,7 +139,7 @@ target_link_libraries(test_plugin GTest::gmock ) -add_library(libtest_common_lite ${protobuf_SHARED_OR_STATIC} +add_library(libtest_common_lite STATIC ${lite_test_proto_files} ) target_link_libraries(libtest_common_lite @@ -163,11 +147,6 @@ target_link_libraries(libtest_common_lite ${protobuf_ABSL_USED_TARGETS} GTest::gmock ) -if(protobuf_BUILD_SHARED_LIBS) - target_compile_definitions(libtest_common_lite - PUBLIC PROTOBUF_USE_DLLS - PRIVATE LIBPROTOBUF_TEST_EXPORTS) -endif() add_executable(lite-test ${protobuf_lite_test_files} @@ -206,8 +185,8 @@ if (protobuf_BUILD_LIBUPB) OUT_VAR pb_generated_files IMPORT_DIRS ${protobuf_SOURCE_DIR}/src IMPORT_DIRS ${protobuf_SOURCE_DIR} - PLUGIN protoc-gen-${generator}=$ - DEPENDENCIES $ + PLUGIN protoc-gen-${generator}=$ + DEPENDENCIES $ ) set(upb_test_proto_genfiles ${upb_test_proto_genfiles} ${pb_generated_files}) endforeach() @@ -219,8 +198,8 @@ if (protobuf_BUILD_LIBUPB) ${upb_test_util_files}) target_link_libraries(upb-test - libprotobuf - libupb + ${protobuf_LIB_PROTOBUF} + ${protobuf_LIB_UPB} ${protobuf_ABSL_USED_TARGETS} ${protobuf_ABSL_USED_TEST_TARGETS} GTest::gmock_main) @@ -239,7 +218,9 @@ add_custom_target(restore-installed-headers) file(GLOB_RECURSE _local_hdrs "${PROJECT_SOURCE_DIR}/src/*.h" - "${PROJECT_SOURCE_DIR}/src/*.inc") + "${PROJECT_SOURCE_DIR}/src/*.inc" + "${PROJECT_SOURCE_DIR}/upb/*.h" +) # Exclude the bootstrapping that are directly used by tests. set(_exclude_hdrs @@ -250,7 +231,7 @@ set(_exclude_hdrs # Exclude test library headers. list(APPEND _exclude_hdrs ${test_util_hdrs} ${lite_test_util_hdrs} ${common_test_hdrs} - ${compiler_test_utils_hdrs}) + ${compiler_test_utils_hdrs} ${upb_test_util_files}) foreach(_hdr ${_exclude_hdrs}) list(REMOVE_ITEM _local_hdrs ${_hdr}) endforeach() diff --git a/cmake/upb_generators.cmake b/cmake/upb_generators.cmake index 2944dc5dc8..b2e66b130e 100644 --- a/cmake/upb_generators.cmake +++ b/cmake/upb_generators.cmake @@ -14,11 +14,12 @@ foreach(generator upb upbdefs upb_minitable) ${bootstrap_sources} ${protobuf_version_rc_file} ) - target_include_directories(protoc-gen-${generator} PUBLIC ${bootstrap_cmake_dir}) + target_include_directories(protoc-gen-${generator} PRIVATE ${bootstrap_cmake_dir}) target_link_libraries(protoc-gen-${generator} - libprotobuf - libupb + ${protobuf_LIB_PROTOBUF} + ${protobuf_LIB_UPB} ${protobuf_ABSL_USED_TARGETS} ) set_target_properties(protoc-gen-${generator} PROPERTIES VERSION ${protobuf_VERSION}) + add_executable(protobuf::protoc-gen-${generator} ALIAS protoc-gen-${generator}) endforeach() diff --git a/conformance/BUILD.bazel b/conformance/BUILD.bazel index f146052d3d..0ce2cd82ec 100644 --- a/conformance/BUILD.bazel +++ b/conformance/BUILD.bazel @@ -36,9 +36,6 @@ exports_files([ "text_format_failure_list_python.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_jruby.txt", - "text_format_failure_list_jruby_ffi.txt", ]) cc_proto_library( @@ -274,6 +271,8 @@ java_binary( "//:protobuf_javalite", "//:test_messages_proto2_java_proto_lite", "//:test_messages_proto3_java_proto_lite", + "//src/google/protobuf/editions:test_messages_proto2_editions_java_proto_lite", + "//src/google/protobuf/editions:test_messages_proto3_editions_java_proto_lite", ], ) @@ -377,6 +376,7 @@ ruby_binary( deps = [ ":conformance_ruby_proto", "//ruby:conformance_test_ruby_proto", + "//ruby:protobuf", ], ) diff --git a/conformance/ConformanceJavaLite.java b/conformance/ConformanceJavaLite.java index ac4ed1f636..33830e0435 100644 --- a/conformance/ConformanceJavaLite.java +++ b/conformance/ConformanceJavaLite.java @@ -5,6 +5,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +import com.google.protobuf.AbstractMessageLite; import com.google.protobuf.ByteString; import com.google.protobuf.CodedInputStream; import com.google.protobuf.ExtensionRegistryLite; @@ -15,6 +16,8 @@ import com.google.protobuf.conformance.Conformance; import com.google.protobuf_test_messages.proto2.TestMessagesProto2; import com.google.protobuf_test_messages.proto2.TestMessagesProto2.TestAllTypesProto2; import com.google.protobuf_test_messages.proto3.TestMessagesProto3; +import com.google.protobuf_test_messages.editions.proto2.TestMessagesProto2Editions; +import com.google.protobuf_test_messages.editions.proto3.TestMessagesProto3Editions; import com.google.protobuf_test_messages.proto3.TestMessagesProto3.TestAllTypesProto3; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -203,42 +206,62 @@ class ConformanceJavaLite { return messages.get(0); } + private Class createTestMessage(String messageType) { + switch (messageType) { + case "protobuf_test_messages.proto3.TestAllTypesProto3": + return TestAllTypesProto3.class; + case "protobuf_test_messages.proto2.TestAllTypesProto2": + return TestAllTypesProto2.class; + case "protobuf_test_messages.editions.proto3.TestAllTypesProto3": + return TestMessagesProto3Editions.TestAllTypesProto3.class; + case "protobuf_test_messages.editions.proto2.TestAllTypesProto2": + return TestMessagesProto2Editions.TestAllTypesProto2.class; + default: + throw new IllegalArgumentException( + "Protobuf request has unexpected payload type: " + messageType); + } + } + + private Class createTestFile(String messageType) { + switch (messageType) { + case "protobuf_test_messages.proto3.TestAllTypesProto3": + return TestMessagesProto3.class; + case "protobuf_test_messages.proto2.TestAllTypesProto2": + return TestMessagesProto2.class; + case "protobuf_test_messages.editions.proto3.TestAllTypesProto3": + return TestMessagesProto3Editions.class; + case "protobuf_test_messages.editions.proto2.TestAllTypesProto2": + return TestMessagesProto2Editions.class; + default: + throw new IllegalArgumentException( + "Protobuf request has unexpected payload type: " + messageType); + } + } + + @SuppressWarnings("unchecked") private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) { com.google.protobuf.MessageLite testMessage; - boolean isProto3 = - request.getMessageType().equals("protobuf_test_messages.proto3.TestAllTypesProto3"); - boolean isProto2 = - request.getMessageType().equals("protobuf_test_messages.proto2.TestAllTypesProto2"); - + String messageType = request.getMessageType(); switch (request.getPayloadCase()) { case PROTOBUF_PAYLOAD: { - if (isProto3) { - try { - ExtensionRegistryLite extensions = ExtensionRegistryLite.newInstance(); - TestMessagesProto3.registerAllExtensions(extensions); - testMessage = - parseBinary( - request.getProtobufPayload(), TestAllTypesProto3.parser(), extensions); - } catch (InvalidProtocolBufferException e) { - return Conformance.ConformanceResponse.newBuilder() - .setParseError(e.getMessage()) - .build(); - } - } else if (isProto2) { - try { - ExtensionRegistryLite extensions = ExtensionRegistryLite.newInstance(); - TestMessagesProto2.registerAllExtensions(extensions); - testMessage = - parseBinary( - request.getProtobufPayload(), TestAllTypesProto2.parser(), extensions); - } catch (InvalidProtocolBufferException e) { - return Conformance.ConformanceResponse.newBuilder() - .setParseError(e.getMessage()) - .build(); - } - } else { - throw new RuntimeException("Protobuf request doesn't have specific payload type."); + try { + ExtensionRegistryLite extensions = ExtensionRegistryLite.newInstance(); + createTestFile(messageType) + .getMethod("registerAllExtensions", ExtensionRegistryLite.class) + .invoke(null, extensions); + testMessage = + parseBinary( + request.getProtobufPayload(), + (Parser) + createTestMessage(messageType).getMethod("parser").invoke(null), + extensions); + } catch (InvalidProtocolBufferException e) { + return Conformance.ConformanceResponse.newBuilder() + .setParseError(e.getMessage()) + .build(); + } catch (Exception e) { + throw new RuntimeException(e); } break; } diff --git a/conformance/conformance_ruby.rb b/conformance/conformance_ruby.rb index 228872d84a..d7202e6b91 100755 --- a/conformance/conformance_ruby.rb +++ b/conformance/conformance_ruby.rb @@ -8,8 +8,11 @@ # https://developers.google.com/open-source/licenses/bsd require 'conformance/conformance_pb' +require 'google/protobuf' require 'google/protobuf/test_messages_proto3_pb' require 'google/protobuf/test_messages_proto2_pb' +require 'google/protobuf/editions/golden/test_messages_proto2_editions_pb' +require 'google/protobuf/editions/golden/test_messages_proto3_editions_pb' $test_count = 0 $verbose = false @@ -20,7 +23,12 @@ def do_test(request) descriptor = Google::Protobuf::DescriptorPool.generated_pool.lookup(request.message_type) unless descriptor - response.skipped = "Unknown message type: " + request.message_type + response.runtime_error = "Unknown message type: " + request.message_type + end + + if request.test_category == :TEXT_FORMAT_TEST + response.skipped = "Ruby doesn't support text format" + return response end begin @@ -45,12 +53,6 @@ def do_test(request) return response end - when :text_payload - begin - response.skipped = "Ruby doesn't support text format" - return response - end - when nil fail "Request didn't have payload" end diff --git a/conformance/failure_list_java_lite.txt b/conformance/failure_list_java_lite.txt index 57a082e602..84606a5173 100644 --- a/conformance/failure_list_java_lite.txt +++ b/conformance/failure_list_java_lite.txt @@ -8,3 +8,7 @@ Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValu Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE +Required.Editions_Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE +Required.Editions_Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE +Required.Editions_Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE +Required.Editions_Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE \ No newline at end of file diff --git a/conformance/failure_list_jruby.txt b/conformance/failure_list_jruby.txt index 9c5e06d622..3825b77083 100644 --- a/conformance/failure_list_jruby.txt +++ b/conformance/failure_list_jruby.txt @@ -69,3 +69,74 @@ Required.Proto3.JsonInput.Int32FieldPlusSign Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt Required.Proto3.JsonInput.StringFieldNotAString +Recommended.Editions_Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput +Recommended.Editions_Proto3.FieldMaskPathsDontRoundTrip.JsonOutput +Recommended.Editions_Proto3.FieldMaskTooManyUnderscore.JsonOutput +Recommended.Editions_Proto2.JsonInput.BoolFieldAllCapitalFalse +Recommended.Editions_Proto2.JsonInput.BoolFieldAllCapitalTrue +Recommended.Editions_Proto2.JsonInput.BoolFieldCamelCaseFalse +Recommended.Editions_Proto2.JsonInput.BoolFieldCamelCaseTrue +Recommended.Editions_Proto2.JsonInput.BoolFieldDoubleQuotedFalse +Recommended.Editions_Proto2.JsonInput.BoolFieldDoubleQuotedTrue +Recommended.Editions_Proto2.JsonInput.BoolMapFieldKeyNotQuoted +Recommended.Editions_Proto2.JsonInput.DoubleFieldInfinityNotQuoted +Recommended.Editions_Proto2.JsonInput.DoubleFieldNanNotQuoted +Recommended.Editions_Proto2.JsonInput.DoubleFieldNegativeInfinityNotQuoted +Recommended.Editions_Proto2.JsonInput.FieldNameDuplicate +Recommended.Editions_Proto2.JsonInput.FieldNameExtension.Validator +Recommended.Editions_Proto2.JsonInput.FieldNameNotQuoted +Recommended.Editions_Proto2.JsonInput.FloatFieldInfinityNotQuoted +Recommended.Editions_Proto2.JsonInput.FloatFieldNanNotQuoted +Recommended.Editions_Proto2.JsonInput.FloatFieldNegativeInfinityNotQuoted +Recommended.Editions_Proto2.JsonInput.Int32MapFieldKeyNotQuoted +Recommended.Editions_Proto2.JsonInput.Int64MapFieldKeyNotQuoted +Recommended.Editions_Proto2.JsonInput.JsonWithComments +Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteBoth +Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteKey +Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteValue +Recommended.Editions_Proto2.JsonInput.StringFieldSurrogateInWrongOrder +Recommended.Editions_Proto2.JsonInput.StringFieldUnpairedHighSurrogate +Recommended.Editions_Proto2.JsonInput.StringFieldUnpairedLowSurrogate +Recommended.Editions_Proto2.JsonInput.Uint32MapFieldKeyNotQuoted +Recommended.Editions_Proto2.JsonInput.Uint64MapFieldKeyNotQuoted +Recommended.Editions_Proto3.JsonInput.BoolFieldAllCapitalFalse +Recommended.Editions_Proto3.JsonInput.BoolFieldAllCapitalTrue +Recommended.Editions_Proto3.JsonInput.BoolFieldCamelCaseFalse +Recommended.Editions_Proto3.JsonInput.BoolFieldCamelCaseTrue +Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedFalse +Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedTrue +Recommended.Editions_Proto3.JsonInput.BoolMapFieldKeyNotQuoted +Recommended.Editions_Proto3.JsonInput.DoubleFieldInfinityNotQuoted +Recommended.Editions_Proto3.JsonInput.DoubleFieldNanNotQuoted +Recommended.Editions_Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted +Recommended.Editions_Proto3.JsonInput.FieldMaskInvalidCharacter +Recommended.Editions_Proto3.JsonInput.FieldNameDuplicate +Recommended.Editions_Proto3.JsonInput.FieldNameNotQuoted +Recommended.Editions_Proto3.JsonInput.FloatFieldInfinityNotQuoted +Recommended.Editions_Proto3.JsonInput.FloatFieldNanNotQuoted +Recommended.Editions_Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted +Recommended.Editions_Proto3.JsonInput.Int32MapFieldKeyNotQuoted +Recommended.Editions_Proto3.JsonInput.Int64MapFieldKeyNotQuoted +Recommended.Editions_Proto3.JsonInput.JsonWithComments +Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteBoth +Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteKey +Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteValue +Recommended.Editions_Proto3.JsonInput.StringFieldSurrogateInWrongOrder +Recommended.Editions_Proto3.JsonInput.StringFieldUnpairedHighSurrogate +Recommended.Editions_Proto3.JsonInput.StringFieldUnpairedLowSurrogate +Recommended.Editions_Proto3.JsonInput.Uint32MapFieldKeyNotQuoted +Recommended.Editions_Proto3.JsonInput.Uint64MapFieldKeyNotQuoted +Required.Editions_Proto2.JsonInput.EnumFieldNotQuoted +Required.Editions_Proto2.JsonInput.Int32FieldLeadingZero +Required.Editions_Proto2.JsonInput.Int32FieldNegativeWithLeadingZero +Required.Editions_Proto2.JsonInput.Int32FieldPlusSign +Required.Editions_Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool +Required.Editions_Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt +Required.Editions_Proto2.JsonInput.StringFieldNotAString +Required.Editions_Proto3.JsonInput.EnumFieldNotQuoted +Required.Editions_Proto3.JsonInput.Int32FieldLeadingZero +Required.Editions_Proto3.JsonInput.Int32FieldNegativeWithLeadingZero +Required.Editions_Proto3.JsonInput.Int32FieldPlusSign +Required.Editions_Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool +Required.Editions_Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt +Required.Editions_Proto3.JsonInput.StringFieldNotAString diff --git a/conformance/text_format_failure_list_jruby.txt b/conformance/text_format_failure_list_jruby.txt deleted file mode 100644 index 404b64a584..0000000000 --- a/conformance/text_format_failure_list_jruby.txt +++ /dev/null @@ -1,8 +0,0 @@ -Recommended.Proto3.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput -Recommended.Proto3.ProtobufInput.GroupUnknownFields_Print.TextFormatOutput -Recommended.Proto3.ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput -Recommended.Proto3.ProtobufInput.MessageUnknownFields_Print.TextFormatOutput -Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput -Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Print.TextFormatOutput -Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput -Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Print.TextFormatOutput diff --git a/conformance/text_format_failure_list_ruby.txt b/conformance/text_format_failure_list_ruby.txt deleted file mode 100644 index 404b64a584..0000000000 --- a/conformance/text_format_failure_list_ruby.txt +++ /dev/null @@ -1,8 +0,0 @@ -Recommended.Proto3.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput -Recommended.Proto3.ProtobufInput.GroupUnknownFields_Print.TextFormatOutput -Recommended.Proto3.ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput -Recommended.Proto3.ProtobufInput.MessageUnknownFields_Print.TextFormatOutput -Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput -Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Print.TextFormatOutput -Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput -Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Print.TextFormatOutput diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestFeatures.pb.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestFeatures.pb.cs index e8f84cba39..548a252dc4 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestFeatures.pb.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestFeatures.pb.cs @@ -29,45 +29,40 @@ namespace Pb { "c3NhZ2UaTQoGTmVzdGVkMkMKC3Rlc3RfbmVzdGVkEhsuZ29vZ2xlLnByb3Rv", "YnVmLkZlYXR1cmVTZXQYjU4gASgLMhAucGIuVGVzdEZlYXR1cmVzMkQKDHRl", "c3RfbWVzc2FnZRIbLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJlU2V0GI5OIAEo", - "CzIQLnBiLlRlc3RGZWF0dXJlcyL9CgoMVGVzdEZlYXR1cmVzElEKEGludF9m", - "aWxlX2ZlYXR1cmUYASABKAVCN4gBAZgBAaIBBxICLTIY5geiAQcSAi0zGOcH", - "ogEGEgExGOgHogEHEgEyGJ2NBqIBBxIBMxiejQYSNAobaW50X2V4dGVuc2lv", - "bl9yYW5nZV9mZWF0dXJlGAIgASgFQg+IAQGYAQKiAQYSATEY5gcSLAoTaW50", - "X21lc3NhZ2VfZmVhdHVyZRgDIAEoBUIPiAEBmAEDogEGEgExGOYHEioKEWlu", - "dF9maWVsZF9mZWF0dXJlGAQgASgFQg+IAQGYAQSiAQYSATEY5gcSKgoRaW50", - "X29uZW9mX2ZlYXR1cmUYBSABKAVCD4gBAZgBBaIBBhIBMRjmBxIpChBpbnRf", - "ZW51bV9mZWF0dXJlGAYgASgFQg+IAQGYAQaiAQYSATEY5gcSLwoWaW50X2Vu", - "dW1fZW50cnlfZmVhdHVyZRgHIAEoBUIPiAEBmAEHogEGEgExGOYHEiwKE2lu", - "dF9zZXJ2aWNlX2ZlYXR1cmUYCCABKAVCD4gBAZgBCKIBBhIBMRjmBxIrChJp", - "bnRfbWV0aG9kX2ZlYXR1cmUYCSABKAVCD4gBAZgBCaIBBhIBMRjmBxJFChRp", - "bnRfbXVsdGlwbGVfZmVhdHVyZRgKIAEoBUIniAEBmAEBmAEEmAEDmAEGmAEH", - "mAEImAEJmAEFmAECogEGEgExGOYHEjwKEmJvb2xfZmllbGRfZmVhdHVyZRgL", - "IAEoCEIgiAEBmAEEogEKEgVmYWxzZRjmB6IBChIEdHJ1ZRidjQYSOgoTZmxv", - "YXRfZmllbGRfZmVhdHVyZRgMIAEoAkIdiAEBmAEEogEIEgMxLjEY5geiAQkS", - "AzEuMhidjQYSzAEKFW1lc3NhZ2VfZmllbGRfZmVhdHVyZRgNIAEoCzIfLnBi", - "LlRlc3RGZWF0dXJlcy5NZXNzYWdlRmVhdHVyZUKLAYgBAZgBBKIBEhIMaW50", - "X2ZpZWxkOiAyGJ2NBqIBGhIUc3RyaW5nX2ZpZWxkOiAnMjAyNCcYno0GogFI", - "EkNib29sX2ZpZWxkOiB0cnVlIGludF9maWVsZDogMSBmbG9hdF9maWVsZDog", - "MS41IHN0cmluZ19maWVsZDogJzIwMjMnGOgHogEFEgAY5gcSnAEKEmVudW1f", - "ZmllbGRfZmVhdHVyZRgOIAEoDjIcLnBiLlRlc3RGZWF0dXJlcy5FbnVtRmVh", - "dHVyZUJiiAEBmAEEogEeEhlURVNUX0VOVU1fRkVBVFVSRV9VTktOT1dOGOYH", - "ogEQEgtFTlVNX1ZBTFVFMRjoB6IBERILRU5VTV9WQUxVRTIYnY0GogEREgtF", - "TlVNX1ZBTFVFMxiejQYSQwoSaW50X3NvdXJjZV9mZWF0dXJlGA8gASgFQieI", - "AQKYAQGYAQSYAQOYAQaYAQeYAQiYAQmYAQWYAQKiAQYSATEY5gcSSwoVc3Ry", - "aW5nX3NvdXJjZV9mZWF0dXJlGBAgASgJQiyIAQKYAQGYAQSYAQOYAQaYAQeY", - "AQiYAQmYAQWYAQKiAQsSBicyMDIzJxjmBxpiCg5NZXNzYWdlRmVhdHVyZRIS", - "Cgpib29sX2ZpZWxkGAEgASgIEhEKCWludF9maWVsZBgCIAEoBRITCgtmbG9h", - "dF9maWVsZBgDIAEoAhIUCgxzdHJpbmdfZmllbGQYBCABKAkigQEKC0VudW1G", - "ZWF0dXJlEh0KGVRFU1RfRU5VTV9GRUFUVVJFX1VOS05PV04QABIPCgtFTlVN", - "X1ZBTFVFMRABEg8KC0VOVU1fVkFMVUUyEAISDwoLRU5VTV9WQUxVRTMQAxIP", - "CgtFTlVNX1ZBTFVFNBAEEg8KC0VOVU1fVkFMVUU1EAU6PAoEdGVzdBIbLmdv", - "b2dsZS5wcm90b2J1Zi5GZWF0dXJlU2V0GI9OIAEoCzIQLnBiLlRlc3RGZWF0", - "dXJlcw==")); + "CzIQLnBiLlRlc3RGZWF0dXJlcyLOBwoMVGVzdEZlYXR1cmVzEnUKDGZpbGVf", + "ZmVhdHVyZRgBIAEoDjIPLnBiLkVudW1GZWF0dXJlQk6IAQGYAQGiAQsSBlZB", + "TFVFMRjmB6IBCxIGVkFMVUUyGOcHogELEgZWQUxVRTMY6AeiAQwSBlZBTFVF", + "NBidjQaiAQwSBlZBTFVFNRiejQYSRgoXZXh0ZW5zaW9uX3JhbmdlX2ZlYXR1", + "cmUYAiABKA4yDy5wYi5FbnVtRmVhdHVyZUIUiAEBmAECogELEgZWQUxVRTEY", + "5gcSPgoPbWVzc2FnZV9mZWF0dXJlGAMgASgOMg8ucGIuRW51bUZlYXR1cmVC", + "FIgBAZgBA6IBCxIGVkFMVUUxGOYHEjwKDWZpZWxkX2ZlYXR1cmUYBCABKA4y", + "Dy5wYi5FbnVtRmVhdHVyZUIUiAEBmAEEogELEgZWQUxVRTEY5gcSPAoNb25l", + "b2ZfZmVhdHVyZRgFIAEoDjIPLnBiLkVudW1GZWF0dXJlQhSIAQGYAQWiAQsS", + "BlZBTFVFMRjmBxI7CgxlbnVtX2ZlYXR1cmUYBiABKA4yDy5wYi5FbnVtRmVh", + "dHVyZUIUiAEBmAEGogELEgZWQUxVRTEY5gcSQQoSZW51bV9lbnRyeV9mZWF0", + "dXJlGAcgASgOMg8ucGIuRW51bUZlYXR1cmVCFIgBAZgBB6IBCxIGVkFMVUUx", + "GOYHEj4KD3NlcnZpY2VfZmVhdHVyZRgIIAEoDjIPLnBiLkVudW1GZWF0dXJl", + "QhSIAQGYAQiiAQsSBlZBTFVFMRjmBxI9Cg5tZXRob2RfZmVhdHVyZRgJIAEo", + "DjIPLnBiLkVudW1GZWF0dXJlQhSIAQGYAQmiAQsSBlZBTFVFMRjmBxJXChBt", + "dWx0aXBsZV9mZWF0dXJlGAogASgOMg8ucGIuRW51bUZlYXR1cmVCLIgBAZgB", + "AZgBBJgBA5gBBpgBB5gBCJgBCZgBBZgBAqIBCxIGVkFMVUUxGOYHEjwKEmJv", + "b2xfZmllbGRfZmVhdHVyZRgLIAEoCEIgiAEBmAEEogEKEgVmYWxzZRjmB6IB", + "ChIEdHJ1ZRidjQYSVQoOc291cmNlX2ZlYXR1cmUYDyABKA4yDy5wYi5FbnVt", + "RmVhdHVyZUIsiAECmAEBmAEEmAEDmAEGmAEHmAEImAEJmAEFmAECogELEgZW", + "QUxVRTEY5gcSVgoPc291cmNlX2ZlYXR1cmUyGBAgASgOMg8ucGIuRW51bUZl", + "YXR1cmVCLIgBApgBAZgBBJgBA5gBBpgBB5gBCJgBCZgBBZgBAqIBCxIGVkFM", + "VUUxGOYHKuYBCgtFbnVtRmVhdHVyZRIdChlURVNUX0VOVU1fRkVBVFVSRV9V", + "TktOT1dOEAASCgoGVkFMVUUxEAESCgoGVkFMVUUyEAISCgoGVkFMVUUzEAMS", + "CgoGVkFMVUU0EAQSCgoGVkFMVUU1EAUSCgoGVkFMVUU2EAYSCgoGVkFMVUU3", + "EAcSCgoGVkFMVUU4EAgSCgoGVkFMVUU5EAkSCwoHVkFMVUUxMBAKEgsKB1ZB", + "TFVFMTEQCxILCgdWQUxVRTEyEAwSCwoHVkFMVUUxMxANEgsKB1ZBTFVFMTQQ", + "DhILCgdWQUxVRTE1EA86PAoEdGVzdBIbLmdvb2dsZS5wcm90b2J1Zi5GZWF0", + "dXJlU2V0GI9OIAEoCzIQLnBiLlRlc3RGZWF0dXJlcw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor, }, - new pbr::GeneratedClrTypeInfo(null, new pb::Extension[] { UnittestFeaturesExtensions.Test }, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Pb.EnumFeature), }, new pb::Extension[] { UnittestFeaturesExtensions.Test }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Pb.TestMessage), global::Pb.TestMessage.Parser, null, null, null, new pb::Extension[] { global::Pb.TestMessage.Extensions.TestMessage }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Pb.TestMessage.Types.Nested), global::Pb.TestMessage.Types.Nested.Parser, null, null, null, new pb::Extension[] { global::Pb.TestMessage.Types.Nested.Extensions.TestNested }, null)}), - new pbr::GeneratedClrTypeInfo(typeof(global::Pb.TestFeatures), global::Pb.TestFeatures.Parser, new[]{ "IntFileFeature", "IntExtensionRangeFeature", "IntMessageFeature", "IntFieldFeature", "IntOneofFeature", "IntEnumFeature", "IntEnumEntryFeature", "IntServiceFeature", "IntMethodFeature", "IntMultipleFeature", "BoolFieldFeature", "FloatFieldFeature", "MessageFieldFeature", "EnumFieldFeature", "IntSourceFeature", "StringSourceFeature" }, null, new[]{ typeof(global::Pb.TestFeatures.Types.EnumFeature) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Pb.TestFeatures.Types.MessageFeature), global::Pb.TestFeatures.Types.MessageFeature.Parser, new[]{ "BoolField", "IntField", "FloatField", "StringField" }, null, null, null, null)}) + new pbr::GeneratedClrTypeInfo(typeof(global::Pb.TestFeatures), global::Pb.TestFeatures.Parser, new[]{ "FileFeature", "ExtensionRangeFeature", "MessageFeature", "FieldFeature", "OneofFeature", "EnumFeature", "EnumEntryFeature", "ServiceFeature", "MethodFeature", "MultipleFeature", "BoolFieldFeature", "SourceFeature", "SourceFeature2" }, null, null, null, null) })); } #endregion @@ -79,6 +74,28 @@ namespace Pb { new pb::Extension(9999, pb::FieldCodec.ForMessage(79994, global::Pb.TestFeatures.Parser)); } + #region Enums + public enum EnumFeature { + [pbr::OriginalName("TEST_ENUM_FEATURE_UNKNOWN")] TestEnumFeatureUnknown = 0, + [pbr::OriginalName("VALUE1")] Value1 = 1, + [pbr::OriginalName("VALUE2")] Value2 = 2, + [pbr::OriginalName("VALUE3")] Value3 = 3, + [pbr::OriginalName("VALUE4")] Value4 = 4, + [pbr::OriginalName("VALUE5")] Value5 = 5, + [pbr::OriginalName("VALUE6")] Value6 = 6, + [pbr::OriginalName("VALUE7")] Value7 = 7, + [pbr::OriginalName("VALUE8")] Value8 = 8, + [pbr::OriginalName("VALUE9")] Value9 = 9, + [pbr::OriginalName("VALUE10")] Value10 = 10, + [pbr::OriginalName("VALUE11")] Value11 = 11, + [pbr::OriginalName("VALUE12")] Value12 = 12, + [pbr::OriginalName("VALUE13")] Value13 = 13, + [pbr::OriginalName("VALUE14")] Value14 = 14, + [pbr::OriginalName("VALUE15")] Value15 = 15, + } + + #endregion + #region Messages [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class TestMessage : pb::IMessage @@ -451,22 +468,19 @@ namespace Pb { [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public TestFeatures(TestFeatures other) : this() { _hasBits0 = other._hasBits0; - intFileFeature_ = other.intFileFeature_; - intExtensionRangeFeature_ = other.intExtensionRangeFeature_; - intMessageFeature_ = other.intMessageFeature_; - intFieldFeature_ = other.intFieldFeature_; - intOneofFeature_ = other.intOneofFeature_; - intEnumFeature_ = other.intEnumFeature_; - intEnumEntryFeature_ = other.intEnumEntryFeature_; - intServiceFeature_ = other.intServiceFeature_; - intMethodFeature_ = other.intMethodFeature_; - intMultipleFeature_ = other.intMultipleFeature_; + fileFeature_ = other.fileFeature_; + extensionRangeFeature_ = other.extensionRangeFeature_; + messageFeature_ = other.messageFeature_; + fieldFeature_ = other.fieldFeature_; + oneofFeature_ = other.oneofFeature_; + enumFeature_ = other.enumFeature_; + enumEntryFeature_ = other.enumEntryFeature_; + serviceFeature_ = other.serviceFeature_; + methodFeature_ = other.methodFeature_; + multipleFeature_ = other.multipleFeature_; boolFieldFeature_ = other.boolFieldFeature_; - floatFieldFeature_ = other.floatFieldFeature_; - messageFieldFeature_ = other.messageFieldFeature_ != null ? other.messageFieldFeature_.Clone() : null; - enumFieldFeature_ = other.enumFieldFeature_; - intSourceFeature_ = other.intSourceFeature_; - stringSourceFeature_ = other.stringSourceFeature_; + sourceFeature_ = other.sourceFeature_; + sourceFeature2_ = other.sourceFeature2_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -476,273 +490,273 @@ namespace Pb { return new TestFeatures(this); } - /// Field number for the "int_file_feature" field. - public const int IntFileFeatureFieldNumber = 1; - private readonly static int IntFileFeatureDefaultValue = 0; + /// Field number for the "file_feature" field. + public const int FileFeatureFieldNumber = 1; + private readonly static global::Pb.EnumFeature FileFeatureDefaultValue = global::Pb.EnumFeature.TestEnumFeatureUnknown; - private int intFileFeature_; + private global::Pb.EnumFeature fileFeature_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int IntFileFeature { - get { if ((_hasBits0 & 1) != 0) { return intFileFeature_; } else { return IntFileFeatureDefaultValue; } } + public global::Pb.EnumFeature FileFeature { + get { if ((_hasBits0 & 1) != 0) { return fileFeature_; } else { return FileFeatureDefaultValue; } } set { _hasBits0 |= 1; - intFileFeature_ = value; + fileFeature_ = value; } } - /// Gets whether the "int_file_feature" field is set + /// Gets whether the "file_feature" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasIntFileFeature { + public bool HasFileFeature { get { return (_hasBits0 & 1) != 0; } } - /// Clears the value of the "int_file_feature" field + /// Clears the value of the "file_feature" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearIntFileFeature() { + public void ClearFileFeature() { _hasBits0 &= ~1; } - /// Field number for the "int_extension_range_feature" field. - public const int IntExtensionRangeFeatureFieldNumber = 2; - private readonly static int IntExtensionRangeFeatureDefaultValue = 0; + /// Field number for the "extension_range_feature" field. + public const int ExtensionRangeFeatureFieldNumber = 2; + private readonly static global::Pb.EnumFeature ExtensionRangeFeatureDefaultValue = global::Pb.EnumFeature.TestEnumFeatureUnknown; - private int intExtensionRangeFeature_; + private global::Pb.EnumFeature extensionRangeFeature_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int IntExtensionRangeFeature { - get { if ((_hasBits0 & 2) != 0) { return intExtensionRangeFeature_; } else { return IntExtensionRangeFeatureDefaultValue; } } + public global::Pb.EnumFeature ExtensionRangeFeature { + get { if ((_hasBits0 & 2) != 0) { return extensionRangeFeature_; } else { return ExtensionRangeFeatureDefaultValue; } } set { _hasBits0 |= 2; - intExtensionRangeFeature_ = value; + extensionRangeFeature_ = value; } } - /// Gets whether the "int_extension_range_feature" field is set + /// Gets whether the "extension_range_feature" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasIntExtensionRangeFeature { + public bool HasExtensionRangeFeature { get { return (_hasBits0 & 2) != 0; } } - /// Clears the value of the "int_extension_range_feature" field + /// Clears the value of the "extension_range_feature" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearIntExtensionRangeFeature() { + public void ClearExtensionRangeFeature() { _hasBits0 &= ~2; } - /// Field number for the "int_message_feature" field. - public const int IntMessageFeatureFieldNumber = 3; - private readonly static int IntMessageFeatureDefaultValue = 0; + /// Field number for the "message_feature" field. + public const int MessageFeatureFieldNumber = 3; + private readonly static global::Pb.EnumFeature MessageFeatureDefaultValue = global::Pb.EnumFeature.TestEnumFeatureUnknown; - private int intMessageFeature_; + private global::Pb.EnumFeature messageFeature_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int IntMessageFeature { - get { if ((_hasBits0 & 4) != 0) { return intMessageFeature_; } else { return IntMessageFeatureDefaultValue; } } + public global::Pb.EnumFeature MessageFeature { + get { if ((_hasBits0 & 4) != 0) { return messageFeature_; } else { return MessageFeatureDefaultValue; } } set { _hasBits0 |= 4; - intMessageFeature_ = value; + messageFeature_ = value; } } - /// Gets whether the "int_message_feature" field is set + /// Gets whether the "message_feature" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasIntMessageFeature { + public bool HasMessageFeature { get { return (_hasBits0 & 4) != 0; } } - /// Clears the value of the "int_message_feature" field + /// Clears the value of the "message_feature" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearIntMessageFeature() { + public void ClearMessageFeature() { _hasBits0 &= ~4; } - /// Field number for the "int_field_feature" field. - public const int IntFieldFeatureFieldNumber = 4; - private readonly static int IntFieldFeatureDefaultValue = 0; + /// Field number for the "field_feature" field. + public const int FieldFeatureFieldNumber = 4; + private readonly static global::Pb.EnumFeature FieldFeatureDefaultValue = global::Pb.EnumFeature.TestEnumFeatureUnknown; - private int intFieldFeature_; + private global::Pb.EnumFeature fieldFeature_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int IntFieldFeature { - get { if ((_hasBits0 & 8) != 0) { return intFieldFeature_; } else { return IntFieldFeatureDefaultValue; } } + public global::Pb.EnumFeature FieldFeature { + get { if ((_hasBits0 & 8) != 0) { return fieldFeature_; } else { return FieldFeatureDefaultValue; } } set { _hasBits0 |= 8; - intFieldFeature_ = value; + fieldFeature_ = value; } } - /// Gets whether the "int_field_feature" field is set + /// Gets whether the "field_feature" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasIntFieldFeature { + public bool HasFieldFeature { get { return (_hasBits0 & 8) != 0; } } - /// Clears the value of the "int_field_feature" field + /// Clears the value of the "field_feature" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearIntFieldFeature() { + public void ClearFieldFeature() { _hasBits0 &= ~8; } - /// Field number for the "int_oneof_feature" field. - public const int IntOneofFeatureFieldNumber = 5; - private readonly static int IntOneofFeatureDefaultValue = 0; + /// Field number for the "oneof_feature" field. + public const int OneofFeatureFieldNumber = 5; + private readonly static global::Pb.EnumFeature OneofFeatureDefaultValue = global::Pb.EnumFeature.TestEnumFeatureUnknown; - private int intOneofFeature_; + private global::Pb.EnumFeature oneofFeature_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int IntOneofFeature { - get { if ((_hasBits0 & 16) != 0) { return intOneofFeature_; } else { return IntOneofFeatureDefaultValue; } } + public global::Pb.EnumFeature OneofFeature { + get { if ((_hasBits0 & 16) != 0) { return oneofFeature_; } else { return OneofFeatureDefaultValue; } } set { _hasBits0 |= 16; - intOneofFeature_ = value; + oneofFeature_ = value; } } - /// Gets whether the "int_oneof_feature" field is set + /// Gets whether the "oneof_feature" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasIntOneofFeature { + public bool HasOneofFeature { get { return (_hasBits0 & 16) != 0; } } - /// Clears the value of the "int_oneof_feature" field + /// Clears the value of the "oneof_feature" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearIntOneofFeature() { + public void ClearOneofFeature() { _hasBits0 &= ~16; } - /// Field number for the "int_enum_feature" field. - public const int IntEnumFeatureFieldNumber = 6; - private readonly static int IntEnumFeatureDefaultValue = 0; + /// Field number for the "enum_feature" field. + public const int EnumFeatureFieldNumber = 6; + private readonly static global::Pb.EnumFeature EnumFeatureDefaultValue = global::Pb.EnumFeature.TestEnumFeatureUnknown; - private int intEnumFeature_; + private global::Pb.EnumFeature enumFeature_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int IntEnumFeature { - get { if ((_hasBits0 & 32) != 0) { return intEnumFeature_; } else { return IntEnumFeatureDefaultValue; } } + public global::Pb.EnumFeature EnumFeature { + get { if ((_hasBits0 & 32) != 0) { return enumFeature_; } else { return EnumFeatureDefaultValue; } } set { _hasBits0 |= 32; - intEnumFeature_ = value; + enumFeature_ = value; } } - /// Gets whether the "int_enum_feature" field is set + /// Gets whether the "enum_feature" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasIntEnumFeature { + public bool HasEnumFeature { get { return (_hasBits0 & 32) != 0; } } - /// Clears the value of the "int_enum_feature" field + /// Clears the value of the "enum_feature" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearIntEnumFeature() { + public void ClearEnumFeature() { _hasBits0 &= ~32; } - /// Field number for the "int_enum_entry_feature" field. - public const int IntEnumEntryFeatureFieldNumber = 7; - private readonly static int IntEnumEntryFeatureDefaultValue = 0; + /// Field number for the "enum_entry_feature" field. + public const int EnumEntryFeatureFieldNumber = 7; + private readonly static global::Pb.EnumFeature EnumEntryFeatureDefaultValue = global::Pb.EnumFeature.TestEnumFeatureUnknown; - private int intEnumEntryFeature_; + private global::Pb.EnumFeature enumEntryFeature_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int IntEnumEntryFeature { - get { if ((_hasBits0 & 64) != 0) { return intEnumEntryFeature_; } else { return IntEnumEntryFeatureDefaultValue; } } + public global::Pb.EnumFeature EnumEntryFeature { + get { if ((_hasBits0 & 64) != 0) { return enumEntryFeature_; } else { return EnumEntryFeatureDefaultValue; } } set { _hasBits0 |= 64; - intEnumEntryFeature_ = value; + enumEntryFeature_ = value; } } - /// Gets whether the "int_enum_entry_feature" field is set + /// Gets whether the "enum_entry_feature" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasIntEnumEntryFeature { + public bool HasEnumEntryFeature { get { return (_hasBits0 & 64) != 0; } } - /// Clears the value of the "int_enum_entry_feature" field + /// Clears the value of the "enum_entry_feature" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearIntEnumEntryFeature() { + public void ClearEnumEntryFeature() { _hasBits0 &= ~64; } - /// Field number for the "int_service_feature" field. - public const int IntServiceFeatureFieldNumber = 8; - private readonly static int IntServiceFeatureDefaultValue = 0; + /// Field number for the "service_feature" field. + public const int ServiceFeatureFieldNumber = 8; + private readonly static global::Pb.EnumFeature ServiceFeatureDefaultValue = global::Pb.EnumFeature.TestEnumFeatureUnknown; - private int intServiceFeature_; + private global::Pb.EnumFeature serviceFeature_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int IntServiceFeature { - get { if ((_hasBits0 & 128) != 0) { return intServiceFeature_; } else { return IntServiceFeatureDefaultValue; } } + public global::Pb.EnumFeature ServiceFeature { + get { if ((_hasBits0 & 128) != 0) { return serviceFeature_; } else { return ServiceFeatureDefaultValue; } } set { _hasBits0 |= 128; - intServiceFeature_ = value; + serviceFeature_ = value; } } - /// Gets whether the "int_service_feature" field is set + /// Gets whether the "service_feature" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasIntServiceFeature { + public bool HasServiceFeature { get { return (_hasBits0 & 128) != 0; } } - /// Clears the value of the "int_service_feature" field + /// Clears the value of the "service_feature" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearIntServiceFeature() { + public void ClearServiceFeature() { _hasBits0 &= ~128; } - /// Field number for the "int_method_feature" field. - public const int IntMethodFeatureFieldNumber = 9; - private readonly static int IntMethodFeatureDefaultValue = 0; + /// Field number for the "method_feature" field. + public const int MethodFeatureFieldNumber = 9; + private readonly static global::Pb.EnumFeature MethodFeatureDefaultValue = global::Pb.EnumFeature.TestEnumFeatureUnknown; - private int intMethodFeature_; + private global::Pb.EnumFeature methodFeature_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int IntMethodFeature { - get { if ((_hasBits0 & 256) != 0) { return intMethodFeature_; } else { return IntMethodFeatureDefaultValue; } } + public global::Pb.EnumFeature MethodFeature { + get { if ((_hasBits0 & 256) != 0) { return methodFeature_; } else { return MethodFeatureDefaultValue; } } set { _hasBits0 |= 256; - intMethodFeature_ = value; + methodFeature_ = value; } } - /// Gets whether the "int_method_feature" field is set + /// Gets whether the "method_feature" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasIntMethodFeature { + public bool HasMethodFeature { get { return (_hasBits0 & 256) != 0; } } - /// Clears the value of the "int_method_feature" field + /// Clears the value of the "method_feature" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearIntMethodFeature() { + public void ClearMethodFeature() { _hasBits0 &= ~256; } - /// Field number for the "int_multiple_feature" field. - public const int IntMultipleFeatureFieldNumber = 10; - private readonly static int IntMultipleFeatureDefaultValue = 0; + /// Field number for the "multiple_feature" field. + public const int MultipleFeatureFieldNumber = 10; + private readonly static global::Pb.EnumFeature MultipleFeatureDefaultValue = global::Pb.EnumFeature.TestEnumFeatureUnknown; - private int intMultipleFeature_; + private global::Pb.EnumFeature multipleFeature_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int IntMultipleFeature { - get { if ((_hasBits0 & 512) != 0) { return intMultipleFeature_; } else { return IntMultipleFeatureDefaultValue; } } + public global::Pb.EnumFeature MultipleFeature { + get { if ((_hasBits0 & 512) != 0) { return multipleFeature_; } else { return MultipleFeatureDefaultValue; } } set { _hasBits0 |= 512; - intMultipleFeature_ = value; + multipleFeature_ = value; } } - /// Gets whether the "int_multiple_feature" field is set + /// Gets whether the "multiple_feature" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasIntMultipleFeature { + public bool HasMultipleFeature { get { return (_hasBits0 & 512) != 0; } } - /// Clears the value of the "int_multiple_feature" field + /// Clears the value of the "multiple_feature" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearIntMultipleFeature() { + public void ClearMultipleFeature() { _hasBits0 &= ~512; } @@ -773,125 +787,60 @@ namespace Pb { _hasBits0 &= ~1024; } - /// Field number for the "float_field_feature" field. - public const int FloatFieldFeatureFieldNumber = 12; - private readonly static float FloatFieldFeatureDefaultValue = 0F; + /// Field number for the "source_feature" field. + public const int SourceFeatureFieldNumber = 15; + private readonly static global::Pb.EnumFeature SourceFeatureDefaultValue = global::Pb.EnumFeature.TestEnumFeatureUnknown; - private float floatFieldFeature_; + private global::Pb.EnumFeature sourceFeature_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public float FloatFieldFeature { - get { if ((_hasBits0 & 2048) != 0) { return floatFieldFeature_; } else { return FloatFieldFeatureDefaultValue; } } + public global::Pb.EnumFeature SourceFeature { + get { if ((_hasBits0 & 2048) != 0) { return sourceFeature_; } else { return SourceFeatureDefaultValue; } } set { _hasBits0 |= 2048; - floatFieldFeature_ = value; + sourceFeature_ = value; } } - /// Gets whether the "float_field_feature" field is set + /// Gets whether the "source_feature" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasFloatFieldFeature { + public bool HasSourceFeature { get { return (_hasBits0 & 2048) != 0; } } - /// Clears the value of the "float_field_feature" field + /// Clears the value of the "source_feature" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearFloatFieldFeature() { + public void ClearSourceFeature() { _hasBits0 &= ~2048; } - /// Field number for the "message_field_feature" field. - public const int MessageFieldFeatureFieldNumber = 13; - private global::Pb.TestFeatures.Types.MessageFeature messageFieldFeature_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Pb.TestFeatures.Types.MessageFeature MessageFieldFeature { - get { return messageFieldFeature_; } - set { - messageFieldFeature_ = value; - } - } - - /// Field number for the "enum_field_feature" field. - public const int EnumFieldFeatureFieldNumber = 14; - private readonly static global::Pb.TestFeatures.Types.EnumFeature EnumFieldFeatureDefaultValue = global::Pb.TestFeatures.Types.EnumFeature.TestEnumFeatureUnknown; + /// Field number for the "source_feature2" field. + public const int SourceFeature2FieldNumber = 16; + private readonly static global::Pb.EnumFeature SourceFeature2DefaultValue = global::Pb.EnumFeature.TestEnumFeatureUnknown; - private global::Pb.TestFeatures.Types.EnumFeature enumFieldFeature_; + private global::Pb.EnumFeature sourceFeature2_; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public global::Pb.TestFeatures.Types.EnumFeature EnumFieldFeature { - get { if ((_hasBits0 & 4096) != 0) { return enumFieldFeature_; } else { return EnumFieldFeatureDefaultValue; } } + public global::Pb.EnumFeature SourceFeature2 { + get { if ((_hasBits0 & 4096) != 0) { return sourceFeature2_; } else { return SourceFeature2DefaultValue; } } set { _hasBits0 |= 4096; - enumFieldFeature_ = value; + sourceFeature2_ = value; } } - /// Gets whether the "enum_field_feature" field is set + /// Gets whether the "source_feature2" field is set [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasEnumFieldFeature { + public bool HasSourceFeature2 { get { return (_hasBits0 & 4096) != 0; } } - /// Clears the value of the "enum_field_feature" field + /// Clears the value of the "source_feature2" field [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearEnumFieldFeature() { + public void ClearSourceFeature2() { _hasBits0 &= ~4096; } - /// Field number for the "int_source_feature" field. - public const int IntSourceFeatureFieldNumber = 15; - private readonly static int IntSourceFeatureDefaultValue = 0; - - private int intSourceFeature_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int IntSourceFeature { - get { if ((_hasBits0 & 8192) != 0) { return intSourceFeature_; } else { return IntSourceFeatureDefaultValue; } } - set { - _hasBits0 |= 8192; - intSourceFeature_ = value; - } - } - /// Gets whether the "int_source_feature" field is set - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasIntSourceFeature { - get { return (_hasBits0 & 8192) != 0; } - } - /// Clears the value of the "int_source_feature" field - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearIntSourceFeature() { - _hasBits0 &= ~8192; - } - - /// Field number for the "string_source_feature" field. - public const int StringSourceFeatureFieldNumber = 16; - private readonly static string StringSourceFeatureDefaultValue = ""; - - private string stringSourceFeature_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string StringSourceFeature { - get { return stringSourceFeature_ ?? StringSourceFeatureDefaultValue; } - set { - stringSourceFeature_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - /// Gets whether the "string_source_feature" field is set - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasStringSourceFeature { - get { return stringSourceFeature_ != null; } - } - /// Clears the value of the "string_source_feature" field - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearStringSourceFeature() { - stringSourceFeature_ = null; - } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { @@ -907,22 +856,19 @@ namespace Pb { if (ReferenceEquals(other, this)) { return true; } - if (IntFileFeature != other.IntFileFeature) return false; - if (IntExtensionRangeFeature != other.IntExtensionRangeFeature) return false; - if (IntMessageFeature != other.IntMessageFeature) return false; - if (IntFieldFeature != other.IntFieldFeature) return false; - if (IntOneofFeature != other.IntOneofFeature) return false; - if (IntEnumFeature != other.IntEnumFeature) return false; - if (IntEnumEntryFeature != other.IntEnumEntryFeature) return false; - if (IntServiceFeature != other.IntServiceFeature) return false; - if (IntMethodFeature != other.IntMethodFeature) return false; - if (IntMultipleFeature != other.IntMultipleFeature) return false; + if (FileFeature != other.FileFeature) return false; + if (ExtensionRangeFeature != other.ExtensionRangeFeature) return false; + if (MessageFeature != other.MessageFeature) return false; + if (FieldFeature != other.FieldFeature) return false; + if (OneofFeature != other.OneofFeature) return false; + if (EnumFeature != other.EnumFeature) return false; + if (EnumEntryFeature != other.EnumEntryFeature) return false; + if (ServiceFeature != other.ServiceFeature) return false; + if (MethodFeature != other.MethodFeature) return false; + if (MultipleFeature != other.MultipleFeature) return false; if (BoolFieldFeature != other.BoolFieldFeature) return false; - if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(FloatFieldFeature, other.FloatFieldFeature)) return false; - if (!object.Equals(MessageFieldFeature, other.MessageFieldFeature)) return false; - if (EnumFieldFeature != other.EnumFieldFeature) return false; - if (IntSourceFeature != other.IntSourceFeature) return false; - if (StringSourceFeature != other.StringSourceFeature) return false; + if (SourceFeature != other.SourceFeature) return false; + if (SourceFeature2 != other.SourceFeature2) return false; return Equals(_unknownFields, other._unknownFields); } @@ -930,22 +876,19 @@ namespace Pb { [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override int GetHashCode() { int hash = 1; - if (HasIntFileFeature) hash ^= IntFileFeature.GetHashCode(); - if (HasIntExtensionRangeFeature) hash ^= IntExtensionRangeFeature.GetHashCode(); - if (HasIntMessageFeature) hash ^= IntMessageFeature.GetHashCode(); - if (HasIntFieldFeature) hash ^= IntFieldFeature.GetHashCode(); - if (HasIntOneofFeature) hash ^= IntOneofFeature.GetHashCode(); - if (HasIntEnumFeature) hash ^= IntEnumFeature.GetHashCode(); - if (HasIntEnumEntryFeature) hash ^= IntEnumEntryFeature.GetHashCode(); - if (HasIntServiceFeature) hash ^= IntServiceFeature.GetHashCode(); - if (HasIntMethodFeature) hash ^= IntMethodFeature.GetHashCode(); - if (HasIntMultipleFeature) hash ^= IntMultipleFeature.GetHashCode(); + if (HasFileFeature) hash ^= FileFeature.GetHashCode(); + if (HasExtensionRangeFeature) hash ^= ExtensionRangeFeature.GetHashCode(); + if (HasMessageFeature) hash ^= MessageFeature.GetHashCode(); + if (HasFieldFeature) hash ^= FieldFeature.GetHashCode(); + if (HasOneofFeature) hash ^= OneofFeature.GetHashCode(); + if (HasEnumFeature) hash ^= EnumFeature.GetHashCode(); + if (HasEnumEntryFeature) hash ^= EnumEntryFeature.GetHashCode(); + if (HasServiceFeature) hash ^= ServiceFeature.GetHashCode(); + if (HasMethodFeature) hash ^= MethodFeature.GetHashCode(); + if (HasMultipleFeature) hash ^= MultipleFeature.GetHashCode(); if (HasBoolFieldFeature) hash ^= BoolFieldFeature.GetHashCode(); - if (HasFloatFieldFeature) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(FloatFieldFeature); - if (messageFieldFeature_ != null) hash ^= MessageFieldFeature.GetHashCode(); - if (HasEnumFieldFeature) hash ^= EnumFieldFeature.GetHashCode(); - if (HasIntSourceFeature) hash ^= IntSourceFeature.GetHashCode(); - if (HasStringSourceFeature) hash ^= StringSourceFeature.GetHashCode(); + if (HasSourceFeature) hash ^= SourceFeature.GetHashCode(); + if (HasSourceFeature2) hash ^= SourceFeature2.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -964,69 +907,57 @@ namespace Pb { #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); #else - if (HasIntFileFeature) { + if (HasFileFeature) { output.WriteRawTag(8); - output.WriteInt32(IntFileFeature); + output.WriteEnum((int) FileFeature); } - if (HasIntExtensionRangeFeature) { + if (HasExtensionRangeFeature) { output.WriteRawTag(16); - output.WriteInt32(IntExtensionRangeFeature); + output.WriteEnum((int) ExtensionRangeFeature); } - if (HasIntMessageFeature) { + if (HasMessageFeature) { output.WriteRawTag(24); - output.WriteInt32(IntMessageFeature); + output.WriteEnum((int) MessageFeature); } - if (HasIntFieldFeature) { + if (HasFieldFeature) { output.WriteRawTag(32); - output.WriteInt32(IntFieldFeature); + output.WriteEnum((int) FieldFeature); } - if (HasIntOneofFeature) { + if (HasOneofFeature) { output.WriteRawTag(40); - output.WriteInt32(IntOneofFeature); + output.WriteEnum((int) OneofFeature); } - if (HasIntEnumFeature) { + if (HasEnumFeature) { output.WriteRawTag(48); - output.WriteInt32(IntEnumFeature); + output.WriteEnum((int) EnumFeature); } - if (HasIntEnumEntryFeature) { + if (HasEnumEntryFeature) { output.WriteRawTag(56); - output.WriteInt32(IntEnumEntryFeature); + output.WriteEnum((int) EnumEntryFeature); } - if (HasIntServiceFeature) { + if (HasServiceFeature) { output.WriteRawTag(64); - output.WriteInt32(IntServiceFeature); + output.WriteEnum((int) ServiceFeature); } - if (HasIntMethodFeature) { + if (HasMethodFeature) { output.WriteRawTag(72); - output.WriteInt32(IntMethodFeature); + output.WriteEnum((int) MethodFeature); } - if (HasIntMultipleFeature) { + if (HasMultipleFeature) { output.WriteRawTag(80); - output.WriteInt32(IntMultipleFeature); + output.WriteEnum((int) MultipleFeature); } if (HasBoolFieldFeature) { output.WriteRawTag(88); output.WriteBool(BoolFieldFeature); } - if (HasFloatFieldFeature) { - output.WriteRawTag(101); - output.WriteFloat(FloatFieldFeature); - } - if (messageFieldFeature_ != null) { - output.WriteRawTag(106); - output.WriteMessage(MessageFieldFeature); - } - if (HasEnumFieldFeature) { - output.WriteRawTag(112); - output.WriteEnum((int) EnumFieldFeature); - } - if (HasIntSourceFeature) { + if (HasSourceFeature) { output.WriteRawTag(120); - output.WriteInt32(IntSourceFeature); + output.WriteEnum((int) SourceFeature); } - if (HasStringSourceFeature) { - output.WriteRawTag(130, 1); - output.WriteString(StringSourceFeature); + if (HasSourceFeature2) { + output.WriteRawTag(128, 1); + output.WriteEnum((int) SourceFeature2); } if (_unknownFields != null) { _unknownFields.WriteTo(output); @@ -1038,69 +969,57 @@ namespace Pb { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasIntFileFeature) { + if (HasFileFeature) { output.WriteRawTag(8); - output.WriteInt32(IntFileFeature); + output.WriteEnum((int) FileFeature); } - if (HasIntExtensionRangeFeature) { + if (HasExtensionRangeFeature) { output.WriteRawTag(16); - output.WriteInt32(IntExtensionRangeFeature); + output.WriteEnum((int) ExtensionRangeFeature); } - if (HasIntMessageFeature) { + if (HasMessageFeature) { output.WriteRawTag(24); - output.WriteInt32(IntMessageFeature); + output.WriteEnum((int) MessageFeature); } - if (HasIntFieldFeature) { + if (HasFieldFeature) { output.WriteRawTag(32); - output.WriteInt32(IntFieldFeature); + output.WriteEnum((int) FieldFeature); } - if (HasIntOneofFeature) { + if (HasOneofFeature) { output.WriteRawTag(40); - output.WriteInt32(IntOneofFeature); + output.WriteEnum((int) OneofFeature); } - if (HasIntEnumFeature) { + if (HasEnumFeature) { output.WriteRawTag(48); - output.WriteInt32(IntEnumFeature); + output.WriteEnum((int) EnumFeature); } - if (HasIntEnumEntryFeature) { + if (HasEnumEntryFeature) { output.WriteRawTag(56); - output.WriteInt32(IntEnumEntryFeature); + output.WriteEnum((int) EnumEntryFeature); } - if (HasIntServiceFeature) { + if (HasServiceFeature) { output.WriteRawTag(64); - output.WriteInt32(IntServiceFeature); + output.WriteEnum((int) ServiceFeature); } - if (HasIntMethodFeature) { + if (HasMethodFeature) { output.WriteRawTag(72); - output.WriteInt32(IntMethodFeature); + output.WriteEnum((int) MethodFeature); } - if (HasIntMultipleFeature) { + if (HasMultipleFeature) { output.WriteRawTag(80); - output.WriteInt32(IntMultipleFeature); + output.WriteEnum((int) MultipleFeature); } if (HasBoolFieldFeature) { output.WriteRawTag(88); output.WriteBool(BoolFieldFeature); } - if (HasFloatFieldFeature) { - output.WriteRawTag(101); - output.WriteFloat(FloatFieldFeature); - } - if (messageFieldFeature_ != null) { - output.WriteRawTag(106); - output.WriteMessage(MessageFieldFeature); - } - if (HasEnumFieldFeature) { - output.WriteRawTag(112); - output.WriteEnum((int) EnumFieldFeature); - } - if (HasIntSourceFeature) { + if (HasSourceFeature) { output.WriteRawTag(120); - output.WriteInt32(IntSourceFeature); + output.WriteEnum((int) SourceFeature); } - if (HasStringSourceFeature) { - output.WriteRawTag(130, 1); - output.WriteString(StringSourceFeature); + if (HasSourceFeature2) { + output.WriteRawTag(128, 1); + output.WriteEnum((int) SourceFeature2); } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); @@ -1112,53 +1031,44 @@ namespace Pb { [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public int CalculateSize() { int size = 0; - if (HasIntFileFeature) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntFileFeature); + if (HasFileFeature) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) FileFeature); } - if (HasIntExtensionRangeFeature) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntExtensionRangeFeature); + if (HasExtensionRangeFeature) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ExtensionRangeFeature); } - if (HasIntMessageFeature) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntMessageFeature); + if (HasMessageFeature) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) MessageFeature); } - if (HasIntFieldFeature) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntFieldFeature); + if (HasFieldFeature) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) FieldFeature); } - if (HasIntOneofFeature) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntOneofFeature); + if (HasOneofFeature) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) OneofFeature); } - if (HasIntEnumFeature) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntEnumFeature); + if (HasEnumFeature) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumFeature); } - if (HasIntEnumEntryFeature) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntEnumEntryFeature); + if (HasEnumEntryFeature) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumEntryFeature); } - if (HasIntServiceFeature) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntServiceFeature); + if (HasServiceFeature) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ServiceFeature); } - if (HasIntMethodFeature) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntMethodFeature); + if (HasMethodFeature) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) MethodFeature); } - if (HasIntMultipleFeature) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntMultipleFeature); + if (HasMultipleFeature) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) MultipleFeature); } if (HasBoolFieldFeature) { size += 1 + 1; } - if (HasFloatFieldFeature) { - size += 1 + 4; - } - if (messageFieldFeature_ != null) { - size += 1 + pb::CodedOutputStream.ComputeMessageSize(MessageFieldFeature); - } - if (HasEnumFieldFeature) { - size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumFieldFeature); - } - if (HasIntSourceFeature) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntSourceFeature); + if (HasSourceFeature) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) SourceFeature); } - if (HasStringSourceFeature) { - size += 2 + pb::CodedOutputStream.ComputeStringSize(StringSourceFeature); + if (HasSourceFeature2) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) SourceFeature2); } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); @@ -1172,56 +1082,44 @@ namespace Pb { if (other == null) { return; } - if (other.HasIntFileFeature) { - IntFileFeature = other.IntFileFeature; + if (other.HasFileFeature) { + FileFeature = other.FileFeature; } - if (other.HasIntExtensionRangeFeature) { - IntExtensionRangeFeature = other.IntExtensionRangeFeature; + if (other.HasExtensionRangeFeature) { + ExtensionRangeFeature = other.ExtensionRangeFeature; } - if (other.HasIntMessageFeature) { - IntMessageFeature = other.IntMessageFeature; + if (other.HasMessageFeature) { + MessageFeature = other.MessageFeature; } - if (other.HasIntFieldFeature) { - IntFieldFeature = other.IntFieldFeature; + if (other.HasFieldFeature) { + FieldFeature = other.FieldFeature; } - if (other.HasIntOneofFeature) { - IntOneofFeature = other.IntOneofFeature; + if (other.HasOneofFeature) { + OneofFeature = other.OneofFeature; } - if (other.HasIntEnumFeature) { - IntEnumFeature = other.IntEnumFeature; + if (other.HasEnumFeature) { + EnumFeature = other.EnumFeature; } - if (other.HasIntEnumEntryFeature) { - IntEnumEntryFeature = other.IntEnumEntryFeature; + if (other.HasEnumEntryFeature) { + EnumEntryFeature = other.EnumEntryFeature; } - if (other.HasIntServiceFeature) { - IntServiceFeature = other.IntServiceFeature; + if (other.HasServiceFeature) { + ServiceFeature = other.ServiceFeature; } - if (other.HasIntMethodFeature) { - IntMethodFeature = other.IntMethodFeature; + if (other.HasMethodFeature) { + MethodFeature = other.MethodFeature; } - if (other.HasIntMultipleFeature) { - IntMultipleFeature = other.IntMultipleFeature; + if (other.HasMultipleFeature) { + MultipleFeature = other.MultipleFeature; } if (other.HasBoolFieldFeature) { BoolFieldFeature = other.BoolFieldFeature; } - if (other.HasFloatFieldFeature) { - FloatFieldFeature = other.FloatFieldFeature; + if (other.HasSourceFeature) { + SourceFeature = other.SourceFeature; } - if (other.messageFieldFeature_ != null) { - if (messageFieldFeature_ == null) { - MessageFieldFeature = new global::Pb.TestFeatures.Types.MessageFeature(); - } - MessageFieldFeature.MergeFrom(other.MessageFieldFeature); - } - if (other.HasEnumFieldFeature) { - EnumFieldFeature = other.EnumFieldFeature; - } - if (other.HasIntSourceFeature) { - IntSourceFeature = other.IntSourceFeature; - } - if (other.HasStringSourceFeature) { - StringSourceFeature = other.StringSourceFeature; + if (other.HasSourceFeature2) { + SourceFeature2 = other.SourceFeature2; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -1239,70 +1137,55 @@ namespace Pb { _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; case 8: { - IntFileFeature = input.ReadInt32(); + FileFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 16: { - IntExtensionRangeFeature = input.ReadInt32(); + ExtensionRangeFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 24: { - IntMessageFeature = input.ReadInt32(); + MessageFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 32: { - IntFieldFeature = input.ReadInt32(); + FieldFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 40: { - IntOneofFeature = input.ReadInt32(); + OneofFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 48: { - IntEnumFeature = input.ReadInt32(); + EnumFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 56: { - IntEnumEntryFeature = input.ReadInt32(); + EnumEntryFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 64: { - IntServiceFeature = input.ReadInt32(); + ServiceFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 72: { - IntMethodFeature = input.ReadInt32(); + MethodFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 80: { - IntMultipleFeature = input.ReadInt32(); + MultipleFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 88: { BoolFieldFeature = input.ReadBool(); break; } - case 101: { - FloatFieldFeature = input.ReadFloat(); - break; - } - case 106: { - if (messageFieldFeature_ == null) { - MessageFieldFeature = new global::Pb.TestFeatures.Types.MessageFeature(); - } - input.ReadMessage(MessageFieldFeature); - break; - } - case 112: { - EnumFieldFeature = (global::Pb.TestFeatures.Types.EnumFeature) input.ReadEnum(); - break; - } case 120: { - IntSourceFeature = input.ReadInt32(); + SourceFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } - case 130: { - StringSourceFeature = input.ReadString(); + case 128: { + SourceFeature2 = (global::Pb.EnumFeature) input.ReadEnum(); break; } } @@ -1321,70 +1204,55 @@ namespace Pb { _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { - IntFileFeature = input.ReadInt32(); + FileFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 16: { - IntExtensionRangeFeature = input.ReadInt32(); + ExtensionRangeFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 24: { - IntMessageFeature = input.ReadInt32(); + MessageFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 32: { - IntFieldFeature = input.ReadInt32(); + FieldFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 40: { - IntOneofFeature = input.ReadInt32(); + OneofFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 48: { - IntEnumFeature = input.ReadInt32(); + EnumFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 56: { - IntEnumEntryFeature = input.ReadInt32(); + EnumEntryFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 64: { - IntServiceFeature = input.ReadInt32(); + ServiceFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 72: { - IntMethodFeature = input.ReadInt32(); + MethodFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 80: { - IntMultipleFeature = input.ReadInt32(); + MultipleFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } case 88: { BoolFieldFeature = input.ReadBool(); break; } - case 101: { - FloatFieldFeature = input.ReadFloat(); - break; - } - case 106: { - if (messageFieldFeature_ == null) { - MessageFieldFeature = new global::Pb.TestFeatures.Types.MessageFeature(); - } - input.ReadMessage(MessageFieldFeature); - break; - } - case 112: { - EnumFieldFeature = (global::Pb.TestFeatures.Types.EnumFeature) input.ReadEnum(); - break; - } case 120: { - IntSourceFeature = input.ReadInt32(); + SourceFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } - case 130: { - StringSourceFeature = input.ReadString(); + case 128: { + SourceFeature2 = (global::Pb.EnumFeature) input.ReadEnum(); break; } } @@ -1392,385 +1260,6 @@ namespace Pb { } #endif - #region Nested types - /// Container for nested types declared in the TestFeatures message type. - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static partial class Types { - public enum EnumFeature { - [pbr::OriginalName("TEST_ENUM_FEATURE_UNKNOWN")] TestEnumFeatureUnknown = 0, - [pbr::OriginalName("ENUM_VALUE1")] EnumValue1 = 1, - [pbr::OriginalName("ENUM_VALUE2")] EnumValue2 = 2, - [pbr::OriginalName("ENUM_VALUE3")] EnumValue3 = 3, - [pbr::OriginalName("ENUM_VALUE4")] EnumValue4 = 4, - [pbr::OriginalName("ENUM_VALUE5")] EnumValue5 = 5, - } - - [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] - public sealed partial class MessageFeature : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MessageFeature()); - private pb::UnknownFieldSet _unknownFields; - private int _hasBits0; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public static pbr::MessageDescriptor Descriptor { - get { return global::Pb.TestFeatures.Descriptor.NestedTypes[0]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public MessageFeature() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public MessageFeature(MessageFeature other) : this() { - _hasBits0 = other._hasBits0; - boolField_ = other.boolField_; - intField_ = other.intField_; - floatField_ = other.floatField_; - stringField_ = other.stringField_; - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public MessageFeature Clone() { - return new MessageFeature(this); - } - - /// Field number for the "bool_field" field. - public const int BoolFieldFieldNumber = 1; - private readonly static bool BoolFieldDefaultValue = false; - - private bool boolField_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool BoolField { - get { if ((_hasBits0 & 1) != 0) { return boolField_; } else { return BoolFieldDefaultValue; } } - set { - _hasBits0 |= 1; - boolField_ = value; - } - } - /// Gets whether the "bool_field" field is set - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasBoolField { - get { return (_hasBits0 & 1) != 0; } - } - /// Clears the value of the "bool_field" field - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearBoolField() { - _hasBits0 &= ~1; - } - - /// Field number for the "int_field" field. - public const int IntFieldFieldNumber = 2; - private readonly static int IntFieldDefaultValue = 0; - - private int intField_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int IntField { - get { if ((_hasBits0 & 2) != 0) { return intField_; } else { return IntFieldDefaultValue; } } - set { - _hasBits0 |= 2; - intField_ = value; - } - } - /// Gets whether the "int_field" field is set - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasIntField { - get { return (_hasBits0 & 2) != 0; } - } - /// Clears the value of the "int_field" field - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearIntField() { - _hasBits0 &= ~2; - } - - /// Field number for the "float_field" field. - public const int FloatFieldFieldNumber = 3; - private readonly static float FloatFieldDefaultValue = 0F; - - private float floatField_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public float FloatField { - get { if ((_hasBits0 & 4) != 0) { return floatField_; } else { return FloatFieldDefaultValue; } } - set { - _hasBits0 |= 4; - floatField_ = value; - } - } - /// Gets whether the "float_field" field is set - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasFloatField { - get { return (_hasBits0 & 4) != 0; } - } - /// Clears the value of the "float_field" field - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearFloatField() { - _hasBits0 &= ~4; - } - - /// Field number for the "string_field" field. - public const int StringFieldFieldNumber = 4; - private readonly static string StringFieldDefaultValue = ""; - - private string stringField_; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public string StringField { - get { return stringField_ ?? StringFieldDefaultValue; } - set { - stringField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - /// Gets whether the "string_field" field is set - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool HasStringField { - get { return stringField_ != null; } - } - /// Clears the value of the "string_field" field - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void ClearStringField() { - stringField_ = null; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override bool Equals(object other) { - return Equals(other as MessageFeature); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public bool Equals(MessageFeature other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (BoolField != other.BoolField) return false; - if (IntField != other.IntField) return false; - if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(FloatField, other.FloatField)) return false; - if (StringField != other.StringField) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override int GetHashCode() { - int hash = 1; - if (HasBoolField) hash ^= BoolField.GetHashCode(); - if (HasIntField) hash ^= IntField.GetHashCode(); - if (HasFloatField) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(FloatField); - if (HasStringField) hash ^= StringField.GetHashCode(); - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - if (HasBoolField) { - output.WriteRawTag(8); - output.WriteBool(BoolField); - } - if (HasIntField) { - output.WriteRawTag(16); - output.WriteInt32(IntField); - } - if (HasFloatField) { - output.WriteRawTag(29); - output.WriteFloat(FloatField); - } - if (HasStringField) { - output.WriteRawTag(34); - output.WriteString(StringField); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (HasBoolField) { - output.WriteRawTag(8); - output.WriteBool(BoolField); - } - if (HasIntField) { - output.WriteRawTag(16); - output.WriteInt32(IntField); - } - if (HasFloatField) { - output.WriteRawTag(29); - output.WriteFloat(FloatField); - } - if (HasStringField) { - output.WriteRawTag(34); - output.WriteString(StringField); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public int CalculateSize() { - int size = 0; - if (HasBoolField) { - size += 1 + 1; - } - if (HasIntField) { - size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntField); - } - if (HasFloatField) { - size += 1 + 4; - } - if (HasStringField) { - size += 1 + pb::CodedOutputStream.ComputeStringSize(StringField); - } - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(MessageFeature other) { - if (other == null) { - return; - } - if (other.HasBoolField) { - BoolField = other.BoolField; - } - if (other.HasIntField) { - IntField = other.IntField; - } - if (other.HasFloatField) { - FloatField = other.FloatField; - } - if (other.HasStringField) { - StringField = other.StringField; - } - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 8: { - BoolField = input.ReadBool(); - break; - } - case 16: { - IntField = input.ReadInt32(); - break; - } - case 29: { - FloatField = input.ReadFloat(); - break; - } - case 34: { - StringField = input.ReadString(); - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 8: { - BoolField = input.ReadBool(); - break; - } - case 16: { - IntField = input.ReadInt32(); - break; - } - case 29: { - FloatField = input.ReadFloat(); - break; - } - case 34: { - StringField = input.ReadString(); - break; - } - } - } - } - #endif - - } - - } - #endregion - } #endregion diff --git a/csharp/src/Google.Protobuf.Test/Reflection/FeatureInheritanceTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/FeatureInheritanceTest.cs index 33458f6321..79dbb64531 100644 --- a/csharp/src/Google.Protobuf.Test/Reflection/FeatureInheritanceTest.cs +++ b/csharp/src/Google.Protobuf.Test/Reflection/FeatureInheritanceTest.cs @@ -258,7 +258,8 @@ public class FeatureInheritanceTest } private static int GetTestFeature(FeatureSetDescriptor features) => - (features.Proto.GetExtension(UnittestFeaturesExtensions.Test) ?? new TestFeatures()).IntMultipleFeature; + (int)(features.Proto.GetExtension(UnittestFeaturesExtensions.Test) ?? new TestFeatures()) + .MultipleFeature; private static void SetTestFeature(FileDescriptorProto proto, int value) { @@ -317,7 +318,8 @@ public class FeatureInheritanceTest } private static void SetTestFeature(FeatureSet features, int value) => - features.SetExtension(UnittestFeaturesExtensions.Test, new TestFeatures { IntMultipleFeature = value }); + features.SetExtension(UnittestFeaturesExtensions.Test, + new TestFeatures { MultipleFeature = (Pb.EnumFeature)value }); private static FileDescriptor Build(FileDescriptorProto fileProto) => FileDescriptor.BuildFromByteStrings(new[] { fileProto.ToByteString() }, new ExtensionRegistry { UnittestFeaturesExtensions.Test })[0]; diff --git a/csharp/src/Google.Protobuf.Test/testprotos.pb b/csharp/src/Google.Protobuf.Test/testprotos.pb index bf259eabb7..acd051e24c 100644 Binary files a/csharp/src/Google.Protobuf.Test/testprotos.pb and b/csharp/src/Google.Protobuf.Test/testprotos.pb differ diff --git a/csharp/src/Google.Protobuf/JsonTokenizer.cs b/csharp/src/Google.Protobuf/JsonTokenizer.cs index d80eed98bd..f89e36adf4 100644 --- a/csharp/src/Google.Protobuf/JsonTokenizer.cs +++ b/csharp/src/Google.Protobuf/JsonTokenizer.cs @@ -1,4 +1,4 @@ -#region Copyright notice and license +#region Copyright notice and license // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // @@ -204,14 +204,13 @@ namespace Google.Protobuf while (true) { var next = reader.Read(); - if (next == null) - { - ValidateState(State.ExpectedEndOfDocument, "Unexpected end of document in state: "); - state = State.ReaderExhausted; - return JsonToken.EndDocument; - } - switch (next.Value) + switch (next) { + case -1: + ValidateState(State.ExpectedEndOfDocument, "Unexpected end of document in state: "); + state = State.ReaderExhausted; + return JsonToken.EndDocument; + // Skip whitespace between tokens case ' ': case '\t': @@ -279,11 +278,11 @@ namespace Google.Protobuf case '7': case '8': case '9': - double number = ReadNumber(next.Value); + double number = ReadNumber((char) next); ValidateAndModifyStateForValue("Invalid state to read a number token: "); return JsonToken.Value(number); default: - throw new InvalidJsonException("Invalid first character of token: " + next.Value); + throw new InvalidJsonException($"Invalid first character of token: {(char) next}"); } } } @@ -395,14 +394,15 @@ namespace Google.Protobuf { for (int i = 1; i < text.Length; i++) { - char? next = reader.Read(); - if (next == null) - { - throw reader.CreateException("Unexpected end of text while reading literal token " + text); - } - if (next.Value != text[i]) + int next = reader.Read(); + if (next != text[i]) { - throw reader.CreateException("Unexpected character while reading literal token " + text); + // Only check for "end of text" when we've detected that the character differs from the + // expected one. + var message = next == -1 + ? $"Unexpected end of text while reading literal token {text}" + : $"Unexpected character while reading literal token {text}"; + throw reader.CreateException(message); } } } @@ -422,7 +422,7 @@ namespace Google.Protobuf // Each method returns the character it read that doesn't belong in that part, // so we know what to do next, including pushing the character back at the end. // null is returned for "end of text". - char? next = ReadInt(builder); + int next = ReadInt(builder); if (next == '.') { next = ReadFrac(builder); @@ -433,9 +433,9 @@ namespace Google.Protobuf } // If we read a character which wasn't part of the number, push it back so we can read it again // to parse the next token. - if (next != null) + if (next != -1) { - reader.PushBack(next.Value); + reader.PushBack((char) next); } // TODO: What exception should we throw if the value can't be represented as a double? @@ -461,7 +461,12 @@ namespace Google.Protobuf } } - private char? ReadInt(StringBuilder builder) + /// + /// Copies an integer into a StringBuilder. + /// + /// The builder to read the number into + /// The character following the integer, or -1 for end-of-text. + private int ReadInt(StringBuilder builder) { char first = reader.ReadOrFail("Invalid numeric literal"); if (first < '0' || first > '9') @@ -469,7 +474,7 @@ namespace Google.Protobuf throw reader.CreateException("Invalid numeric literal"); } builder.Append(first); - char? next = ConsumeDigits(builder, out int digitCount); + int next = ConsumeDigits(builder, out int digitCount); if (first == '0' && digitCount != 0) { throw reader.CreateException("Invalid numeric literal: leading 0 for non-zero value."); @@ -477,10 +482,15 @@ namespace Google.Protobuf return next; } - private char? ReadFrac(StringBuilder builder) + /// + /// Copies the fractional part of an integer into a StringBuilder, assuming reader is positioned after a period. + /// + /// The builder to read the number into + /// The character following the fractional part, or -1 for end-of-text. + private int ReadFrac(StringBuilder builder) { builder.Append('.'); // Already consumed this - char? next = ConsumeDigits(builder, out int digitCount); + int next = ConsumeDigits(builder, out int digitCount); if (digitCount == 0) { throw reader.CreateException("Invalid numeric literal: fraction with no trailing digits"); @@ -488,21 +498,26 @@ namespace Google.Protobuf return next; } - private char? ReadExp(StringBuilder builder) + /// + /// Copies the exponent part of a number into a StringBuilder, with an assumption that the reader is already positioned after the "e". + /// + /// The builder to read the number into + /// The character following the exponent, or -1 for end-of-text. + private int ReadExp(StringBuilder builder) { builder.Append('E'); // Already consumed this (or 'e') - char? next = reader.Read(); - if (next == null) + int next = reader.Read(); + if (next == -1) { throw reader.CreateException("Invalid numeric literal: exponent with no trailing digits"); } if (next == '-' || next == '+') { - builder.Append(next.Value); + builder.Append((char) next); } else { - reader.PushBack(next.Value); + reader.PushBack((char) next); } next = ConsumeDigits(builder, out int digitCount); if (digitCount == 0) @@ -512,18 +527,24 @@ namespace Google.Protobuf return next; } - private char? ConsumeDigits(StringBuilder builder, out int count) + /// + /// Copies a sequence of digits into a StringBuilder. + /// + /// The builder to read the number into + /// The number of digits appended to the builder + /// The character following the digits, or -1 for end-of-text. + private int ConsumeDigits(StringBuilder builder, out int count) { count = 0; while (true) { - char? next = reader.Read(); - if (next == null || next.Value < '0' || next.Value > '9') + int next = reader.Read(); + if (next == -1 || next < '0' || next > '9') { return next; } count++; - builder.Append(next.Value); + builder.Append((char) next); } } @@ -683,39 +704,41 @@ namespace Google.Protobuf } /// - /// The buffered next character, if we have one. + /// The buffered next character, if we have one, or -1 if there is no buffered character. /// - private char? nextChar; + private int nextChar = -1; /// - /// Returns the next character in the stream, or null if we have reached the end. + /// Returns the next character in the stream, or -1 if we have reached the end of the stream. /// - /// - internal char? Read() + internal int Read() { - if (nextChar != null) + if (nextChar != -1) { - char? tmp = nextChar; - nextChar = null; + int tmp = nextChar; + nextChar = -1; return tmp; } - int next = reader.Read(); - return next == -1 ? null : (char?) next; + return reader.Read(); } + /// + /// Reads the next character from the underlying reader, throwing an + /// with the specified message if there are no more characters available. + /// internal char ReadOrFail(string messageOnFailure) { - char? next = Read(); - if (next == null) + int next = Read(); + if (next == -1) { throw CreateException(messageOnFailure); } - return next.Value; + return (char) next; } internal void PushBack(char c) { - if (nextChar != null) + if (nextChar != -1) { throw new InvalidOperationException("Cannot push back when already buffering a character"); } diff --git a/csharp/src/Google.Protobuf/Reflection/Descriptor.pb.cs b/csharp/src/Google.Protobuf/Reflection/Descriptor.pb.cs index e7bc8441de..5475d9573f 100644 --- a/csharp/src/Google.Protobuf/Reflection/Descriptor.pb.cs +++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.pb.cs @@ -182,7 +182,7 @@ namespace Google.Protobuf.Reflection { "dmVfaW50X3ZhbHVlGAQgASgEEhoKEm5lZ2F0aXZlX2ludF92YWx1ZRgFIAEo", "AxIUCgxkb3VibGVfdmFsdWUYBiABKAESFAoMc3RyaW5nX3ZhbHVlGAcgASgM", "EhcKD2FnZ3JlZ2F0ZV92YWx1ZRgIIAEoCRozCghOYW1lUGFydBIRCgluYW1l", - "X3BhcnQYASACKAkSFAoMaXNfZXh0ZW5zaW9uGAIgAigIIq0JCgpGZWF0dXJl", + "X3BhcnQYASACKAkSFAoMaXNfZXh0ZW5zaW9uGAIgAigIIrUJCgpGZWF0dXJl", "U2V0EnwKDmZpZWxkX3ByZXNlbmNlGAEgASgOMikuZ29vZ2xlLnByb3RvYnVm", "LkZlYXR1cmVTZXQuRmllbGRQcmVzZW5jZUI5iAEBmAEEmAEBogENEghFWFBM", "SUNJVBjmB6IBDRIISU1QTElDSVQY5weiAQ0SCEVYUExJQ0lUGOgHElwKCWVu", @@ -208,35 +208,35 @@ namespace Google.Protobuf.Reflection { "Z2VFbmNvZGluZxIcChhNRVNTQUdFX0VOQ09ESU5HX1VOS05PV04QABITCg9M", "RU5HVEhfUFJFRklYRUQQARINCglERUxJTUlURUQQAiJICgpKc29uRm9ybWF0", "EhcKE0pTT05fRk9STUFUX1VOS05PV04QABIJCgVBTExPVxABEhYKEkxFR0FD", - "WV9CRVNUX0VGRk9SVBACKgYI6AcQ6QcqBgjpBxDqByoGCOoHEOsHKgYIi04Q", - "kE4qBgiQThCRTkoGCOcHEOgHIsACChJGZWF0dXJlU2V0RGVmYXVsdHMSTgoI", - "ZGVmYXVsdHMYASADKAsyPC5nb29nbGUucHJvdG9idWYuRmVhdHVyZVNldERl", - "ZmF1bHRzLkZlYXR1cmVTZXRFZGl0aW9uRGVmYXVsdBIxCg9taW5pbXVtX2Vk", - "aXRpb24YBCABKA4yGC5nb29nbGUucHJvdG9idWYuRWRpdGlvbhIxCg9tYXhp", - "bXVtX2VkaXRpb24YBSABKA4yGC5nb29nbGUucHJvdG9idWYuRWRpdGlvbhp0", - "ChhGZWF0dXJlU2V0RWRpdGlvbkRlZmF1bHQSKQoHZWRpdGlvbhgDIAEoDjIY", - "Lmdvb2dsZS5wcm90b2J1Zi5FZGl0aW9uEi0KCGZlYXR1cmVzGAIgASgLMhsu", - "Z29vZ2xlLnByb3RvYnVmLkZlYXR1cmVTZXQi1QEKDlNvdXJjZUNvZGVJbmZv", - "EjoKCGxvY2F0aW9uGAEgAygLMiguZ29vZ2xlLnByb3RvYnVmLlNvdXJjZUNv", - "ZGVJbmZvLkxvY2F0aW9uGoYBCghMb2NhdGlvbhIQCgRwYXRoGAEgAygFQgIQ", - "ARIQCgRzcGFuGAIgAygFQgIQARIYChBsZWFkaW5nX2NvbW1lbnRzGAMgASgJ", - "EhkKEXRyYWlsaW5nX2NvbW1lbnRzGAQgASgJEiEKGWxlYWRpbmdfZGV0YWNo", - "ZWRfY29tbWVudHMYBiADKAkinAIKEUdlbmVyYXRlZENvZGVJbmZvEkEKCmFu", - "bm90YXRpb24YASADKAsyLS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkQ29k", - "ZUluZm8uQW5ub3RhdGlvbhrDAQoKQW5ub3RhdGlvbhIQCgRwYXRoGAEgAygF", - "QgIQARITCgtzb3VyY2VfZmlsZRgCIAEoCRINCgViZWdpbhgDIAEoBRILCgNl", - "bmQYBCABKAUSSAoIc2VtYW50aWMYBSABKA4yNi5nb29nbGUucHJvdG9idWYu", - "R2VuZXJhdGVkQ29kZUluZm8uQW5ub3RhdGlvbi5TZW1hbnRpYyIoCghTZW1h", - "bnRpYxIICgROT05FEAASBwoDU0VUEAESCQoFQUxJQVMQAiqSAgoHRWRpdGlv", - "bhITCg9FRElUSU9OX1VOS05PV04QABITCg5FRElUSU9OX1BST1RPMhDmBxIT", - "Cg5FRElUSU9OX1BST1RPMxDnBxIRCgxFRElUSU9OXzIwMjMQ6AcSEQoMRURJ", - "VElPTl8yMDI0EOkHEhcKE0VESVRJT05fMV9URVNUX09OTFkQARIXChNFRElU", - "SU9OXzJfVEVTVF9PTkxZEAISHQoXRURJVElPTl85OTk5N19URVNUX09OTFkQ", - "nY0GEh0KF0VESVRJT05fOTk5OThfVEVTVF9PTkxZEJ6NBhIdChdFRElUSU9O", - "Xzk5OTk5X1RFU1RfT05MWRCfjQYSEwoLRURJVElPTl9NQVgQ/////wdCfgoT", - "Y29tLmdvb2dsZS5wcm90b2J1ZkIQRGVzY3JpcHRvclByb3Rvc0gBWi1nb29n", - "bGUuZ29sYW5nLm9yZy9wcm90b2J1Zi90eXBlcy9kZXNjcmlwdG9ycGL4AQGi", - "AgNHUEKqAhpHb29nbGUuUHJvdG9idWYuUmVmbGVjdGlvbg==")); + "WV9CRVNUX0VGRk9SVBACKgYI6AcQ6QcqBgjpBxDqByoGCOoHEOsHKgYIhk4Q", + "h04qBgiLThCQTioGCJBOEJFOSgYI5wcQ6AciwAIKEkZlYXR1cmVTZXREZWZh", + "dWx0cxJOCghkZWZhdWx0cxgBIAMoCzI8Lmdvb2dsZS5wcm90b2J1Zi5GZWF0", + "dXJlU2V0RGVmYXVsdHMuRmVhdHVyZVNldEVkaXRpb25EZWZhdWx0EjEKD21p", + "bmltdW1fZWRpdGlvbhgEIAEoDjIYLmdvb2dsZS5wcm90b2J1Zi5FZGl0aW9u", + "EjEKD21heGltdW1fZWRpdGlvbhgFIAEoDjIYLmdvb2dsZS5wcm90b2J1Zi5F", + "ZGl0aW9uGnQKGEZlYXR1cmVTZXRFZGl0aW9uRGVmYXVsdBIpCgdlZGl0aW9u", + "GAMgASgOMhguZ29vZ2xlLnByb3RvYnVmLkVkaXRpb24SLQoIZmVhdHVyZXMY", + "AiABKAsyGy5nb29nbGUucHJvdG9idWYuRmVhdHVyZVNldCLVAQoOU291cmNl", + "Q29kZUluZm8SOgoIbG9jYXRpb24YASADKAsyKC5nb29nbGUucHJvdG9idWYu", + "U291cmNlQ29kZUluZm8uTG9jYXRpb24ahgEKCExvY2F0aW9uEhAKBHBhdGgY", + "ASADKAVCAhABEhAKBHNwYW4YAiADKAVCAhABEhgKEGxlYWRpbmdfY29tbWVu", + "dHMYAyABKAkSGQoRdHJhaWxpbmdfY29tbWVudHMYBCABKAkSIQoZbGVhZGlu", + "Z19kZXRhY2hlZF9jb21tZW50cxgGIAMoCSKcAgoRR2VuZXJhdGVkQ29kZUlu", + "Zm8SQQoKYW5ub3RhdGlvbhgBIAMoCzItLmdvb2dsZS5wcm90b2J1Zi5HZW5l", + "cmF0ZWRDb2RlSW5mby5Bbm5vdGF0aW9uGsMBCgpBbm5vdGF0aW9uEhAKBHBh", + "dGgYASADKAVCAhABEhMKC3NvdXJjZV9maWxlGAIgASgJEg0KBWJlZ2luGAMg", + "ASgFEgsKA2VuZBgEIAEoBRJICghzZW1hbnRpYxgFIAEoDjI2Lmdvb2dsZS5w", + "cm90b2J1Zi5HZW5lcmF0ZWRDb2RlSW5mby5Bbm5vdGF0aW9uLlNlbWFudGlj", + "IigKCFNlbWFudGljEggKBE5PTkUQABIHCgNTRVQQARIJCgVBTElBUxACKpIC", + "CgdFZGl0aW9uEhMKD0VESVRJT05fVU5LTk9XThAAEhMKDkVESVRJT05fUFJP", + "VE8yEOYHEhMKDkVESVRJT05fUFJPVE8zEOcHEhEKDEVESVRJT05fMjAyMxDo", + "BxIRCgxFRElUSU9OXzIwMjQQ6QcSFwoTRURJVElPTl8xX1RFU1RfT05MWRAB", + "EhcKE0VESVRJT05fMl9URVNUX09OTFkQAhIdChdFRElUSU9OXzk5OTk3X1RF", + "U1RfT05MWRCdjQYSHQoXRURJVElPTl85OTk5OF9URVNUX09OTFkQno0GEh0K", + "F0VESVRJT05fOTk5OTlfVEVTVF9PTkxZEJ+NBhITCgtFRElUSU9OX01BWBD/", + "////B0J+ChNjb20uZ29vZ2xlLnByb3RvYnVmQhBEZXNjcmlwdG9yUHJvdG9z", + "SAFaLWdvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2Rlc2NyaXB0", + "b3JwYvgBAaICA0dQQqoCGkdvb2dsZS5Qcm90b2J1Zi5SZWZsZWN0aW9u")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.Reflection.Edition), }, null, new pbr::GeneratedClrTypeInfo[] { diff --git a/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs b/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs index 060843677b..7289e44a0f 100644 --- a/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs +++ b/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs @@ -27,6 +27,9 @@ namespace Google.Protobuf.Reflection private readonly IDictionary, EnumValueDescriptor> enumValuesByNumber = new Dictionary, EnumValueDescriptor>(); + private readonly IDictionary enumValuesByName = + new Dictionary(); + private readonly HashSet dependencies = new HashSet(); internal DescriptorPool(IEnumerable dependencyFiles) @@ -129,29 +132,20 @@ namespace Google.Protobuf.Reflection if (descriptorsByName.TryGetValue(fullName, out IDescriptor old)) { - int dotPos = fullName.LastIndexOf('.'); - string message; - if (descriptor.File == old.File) - { - if (dotPos == -1) - { - message = "\"" + fullName + "\" is already defined."; - } - else - { - message = "\"" + fullName.Substring(dotPos + 1) + "\" is already defined in \"" + - fullName.Substring(0, dotPos) + "\"."; - } - } - else - { - message = "\"" + fullName + "\" is already defined in file \"" + old.File.Name + "\"."; - } - throw new DescriptorValidationException(descriptor, message); + throw new DescriptorValidationException(descriptor, + GetDescriptorAlreadyAddedExceptionMessage(descriptor, fullName, old)); } descriptorsByName[fullName] = descriptor; } + private static string GetDescriptorAlreadyAddedExceptionMessage(IDescriptor descriptor, string fullName, IDescriptor old) + { + int dotPos = fullName.LastIndexOf('.'); + return descriptor.File != old.File ? $"\"{fullName}\" is already defined in file \"{old.File.Name}\"." + : dotPos == -1 ? $"{fullName} is already defined." + : $"\"{fullName.Substring(dotPos + 1)}\" is already defined in \"{fullName.Substring(0, dotPos)}\"."; + } + /// /// Verifies that the descriptor's name is valid (i.e. it contains /// only letters, digits and underscores, and does not start with a digit). @@ -167,11 +161,14 @@ namespace Google.Protobuf.Reflection // Symbol name must start with a letter or underscore, and it can contain letters, // numbers and underscores. string name = descriptor.Name; - if (!IsAsciiLetter(name[0]) && name[0] != '_') { + if (!IsAsciiLetter(name[0]) && name[0] != '_') + { ThrowInvalidSymbolNameException(descriptor); } - for (int i = 1; i < name.Length; i++) { - if (!IsAsciiLetter(name[i]) && !IsAsciiDigit(name[i]) && name[i] != '_') { + for (int i = 1; i < name.Length; i++) + { + if (!IsAsciiLetter(name[i]) && !IsAsciiDigit(name[i]) && name[i] != '_') + { ThrowInvalidSymbolNameException(descriptor); } } @@ -199,6 +196,12 @@ namespace Google.Protobuf.Reflection return ret; } + internal EnumValueDescriptor FindEnumValueByName(EnumDescriptor enumDescriptor, string name) + { + enumValuesByName.TryGetValue(new EnumValueByNameDescriptorKey(enumDescriptor, name), out EnumValueDescriptor ret); + return ret; + } + /// /// Adds a field to the fieldsByNumber table. /// @@ -219,17 +222,28 @@ namespace Google.Protobuf.Reflection } /// - /// Adds an enum value to the enumValuesByNumber table. If an enum value - /// with the same type and number already exists, this method does nothing. - /// (This is allowed; the first value defined with the number takes precedence.) + /// Adds an enum value to the enumValuesByNumber and enumValuesByName tables. If an enum value + /// with the same type and number already exists, this method does nothing to enumValuesByNumber. + /// (This is allowed; the first value defined with the number takes precedence.) If an enum + /// value with the same name already exists, this method throws DescriptorValidationException. + /// (It is expected that this method is called after AddSymbol, which would already have thrown + /// an exception in this failure case.) /// - internal void AddEnumValueByNumber(EnumValueDescriptor enumValue) + internal void AddEnumValue(EnumValueDescriptor enumValue) { - ObjectIntPair key = new ObjectIntPair(enumValue.EnumDescriptor, enumValue.Number); - if (!enumValuesByNumber.ContainsKey(key)) + ObjectIntPair numberKey = new ObjectIntPair(enumValue.EnumDescriptor, enumValue.Number); + if (!enumValuesByNumber.ContainsKey(numberKey)) { - enumValuesByNumber[key] = enumValue; + enumValuesByNumber[numberKey] = enumValue; } + + EnumValueByNameDescriptorKey nameKey = new EnumValueByNameDescriptorKey(enumValue.EnumDescriptor, enumValue.Name); + if (enumValuesByName.TryGetValue(nameKey, out EnumValueDescriptor old)) + { + throw new DescriptorValidationException(enumValue, + GetDescriptorAlreadyAddedExceptionMessage(enumValue, enumValue.FullName, old)); + } + enumValuesByName[nameKey] = enumValue; } /// @@ -308,5 +322,37 @@ namespace Google.Protobuf.Reflection return result; } } - } + + /// + /// Struct used to hold the keys for the enumValuesByName table. + /// + private struct EnumValueByNameDescriptorKey : IEquatable + { + private readonly string name; + private readonly IDescriptor descriptor; + + internal EnumValueByNameDescriptorKey(EnumDescriptor descriptor, string valueName) + { + this.descriptor = descriptor; + this.name = valueName; + } + + public bool Equals(EnumValueByNameDescriptorKey other) => + descriptor == other.descriptor + && name == other.name; + + public override bool Equals(object obj) => + obj is EnumValueByNameDescriptorKey pair && Equals(pair); + + public override int GetHashCode() + { + unchecked + { + var hashCode = descriptor.GetHashCode(); + hashCode = (hashCode * 397) ^ (name != null ? name.GetHashCode() : 0); + return hashCode; + } + } + } + } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs index 293fbb24ec..f90352d463 100644 --- a/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs @@ -90,10 +90,8 @@ namespace Google.Protobuf.Reflection /// /// The unqualified name of the value (e.g. "FOO"). /// The value's descriptor, or null if not found. - public EnumValueDescriptor FindValueByName(string name) - { - return File.DescriptorPool.FindSymbol(FullName + "." + name); - } + public EnumValueDescriptor FindValueByName(string name) => + File.DescriptorPool.FindEnumValueByName(this, name); /// /// The (possibly empty) set of custom options for this enum. diff --git a/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs index ef427c6933..5f535f4183 100644 --- a/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs @@ -24,7 +24,7 @@ namespace Google.Protobuf.Reflection Proto = proto; EnumDescriptor = parent; file.DescriptorPool.AddSymbol(this); - file.DescriptorPool.AddEnumValueByNumber(this); + file.DescriptorPool.AddEnumValue(this); } internal EnumValueDescriptorProto Proto { get; } diff --git a/java/core/BUILD.bazel b/java/core/BUILD.bazel index ce6984ad65..f9aaf361bf 100644 --- a/java/core/BUILD.bazel +++ b/java/core/BUILD.bazel @@ -109,8 +109,10 @@ internal_gen_well_known_protos_java( name = "gen_well_known_protos_javalite", javalite = True, deps = [ + ":java_features_proto", "//:any_proto", "//:api_proto", + "//:descriptor_proto", "//:duration_proto", "//:empty_proto", "//:field_mask_proto", @@ -155,7 +157,9 @@ protobuf_java_export( maven_coordinates = "com.google.protobuf:protobuf-javalite:%s" % PROTOBUF_JAVA_VERSION, pom_template = "//java/lite:pom_template.xml", resources = [ + ":java_features_proto", "//:lite_well_known_protos", + "//src/google/protobuf:descriptor_proto_srcs", ], tags = ["manual"], runtime_deps = [":lite_bundle"], @@ -170,7 +174,12 @@ proto_library( name = "java_features_proto", srcs = ["src/main/java/com/google/protobuf/java_features.proto"], strip_import_prefix = "/java/core/src/main/java/com", - visibility = ["//pkg:__pkg__"], + visibility = [ + "//java/kotlin:__pkg__", + "//java/kotlin-lite:__pkg__", + "//java/lite:__pkg__", + "//pkg:__pkg__", + ], deps = ["//:descriptor_proto"], ) diff --git a/java/core/generate-test-sources-build.xml b/java/core/generate-test-sources-build.xml index a818213300..66e8415614 100644 --- a/java/core/generate-test-sources-build.xml +++ b/java/core/generate-test-sources-build.xml @@ -6,6 +6,7 @@ + @@ -18,8 +19,10 @@ + + diff --git a/java/core/src/main/java/com/google/protobuf/ByteString.java b/java/core/src/main/java/com/google/protobuf/ByteString.java index 8ba729c8e6..fcb4c460a2 100644 --- a/java/core/src/main/java/com/google/protobuf/ByteString.java +++ b/java/core/src/main/java/com/google/protobuf/ByteString.java @@ -70,6 +70,11 @@ public abstract class ByteString implements Iterable, Serializable { static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000; // 8k /** Empty {@code ByteString}. */ + // There is a class initialization cycle via LiteralByteString -> LeafByteString -> ByteString. + // In practice the only implementation of LeafByteString outside this file is NioByteString, + // and the only public API that creates LeafByteStrings is in ByteString, so ByteString will + // always be initialized first. + @SuppressWarnings("ClassInitializationDeadlock") public static final ByteString EMPTY = new LiteralByteString(Internal.EMPTY_BYTE_ARRAY); /** diff --git a/java/core/src/main/java/com/google/protobuf/JavaEditionDefaults.java.template b/java/core/src/main/java/com/google/protobuf/JavaEditionDefaults.java.template index d20a721fcd..d50b2ccbe4 100644 --- a/java/core/src/main/java/com/google/protobuf/JavaEditionDefaults.java.template +++ b/java/core/src/main/java/com/google/protobuf/JavaEditionDefaults.java.template @@ -8,4 +8,3 @@ public final class JavaEditionDefaults { private JavaEditionDefaults() {} } - diff --git a/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java b/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java index d08e3ccf46..da53f22e2f 100644 --- a/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java +++ b/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java @@ -1315,12 +1315,12 @@ public class DescriptorsTest { features.setExtension( UnittestFeatures.test, features.getExtension(UnittestFeatures.test).toBuilder() - .setIntMultipleFeature(value) + .setMultipleFeature(UnittestFeatures.EnumFeature.forNumber(value)) .build()); } int getTestFeature(DescriptorProtos.FeatureSet features) { - return features.getExtension(UnittestFeatures.test).getIntMultipleFeature(); + return features.getExtension(UnittestFeatures.test).getMultipleFeature().getNumber(); } FileDescriptor buildFrom(FileDescriptorProto fileProto) throws Exception { diff --git a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java index a66e97959b..920693947e 100644 --- a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java +++ b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java @@ -1385,6 +1385,7 @@ public class GeneratedMessageTest { // ================================================================= // oneof generated code test @Test + @SuppressWarnings("RedundantSetterCall") public void testOneofEnumCase() throws Exception { TestOneof2 message = TestOneof2.newBuilder().setFooInt(123).setFooString("foo").setFooCord("bar").build(); @@ -1400,6 +1401,7 @@ public class GeneratedMessageTest { } @Test + @SuppressWarnings("RedundantSetterCall") public void testSetOneofClearsOthers() throws Exception { TestOneof2.Builder builder = TestOneof2.newBuilder(); TestOneof2 message = builder.setFooInt(123).setFooString("foo").buildPartial(); diff --git a/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java b/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java index e29bb25129..182d9d3877 100644 --- a/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java +++ b/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java @@ -24,6 +24,7 @@ import org.junit.runners.JUnit4; public class LazyMessageLiteTest { @Test + @SuppressWarnings("RedundantSetterCall") public void testSetValues() { LazyNestedInnerMessageLite nested = LazyNestedInnerMessageLite.newBuilder().setNum(3).build(); LazyInnerMessageLite inner = diff --git a/java/core/src/test/proto/com/google/protobuf/any_test.proto b/java/core/src/test/proto/com/google/protobuf/any_test.proto index d180f710f7..36453b5912 100644 --- a/java/core/src/test/proto/com/google/protobuf/any_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/any_test.proto @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto3"; +edition = "2023"; package any_test; diff --git a/java/core/src/test/proto/com/google/protobuf/cached_field_size_test.proto b/java/core/src/test/proto/com/google/protobuf/cached_field_size_test.proto index bcb219e294..bfc81e8ed6 100644 --- a/java/core/src/test/proto/com/google/protobuf/cached_field_size_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/cached_field_size_test.proto @@ -6,7 +6,7 @@ // https://developers.google.com/open-source/licenses/bsd // A regression test for b/74087933 -syntax = "proto2"; +edition = "2023"; package protobuf_unittest; @@ -17,6 +17,6 @@ option optimize_for = CODE_SIZE; option java_multiple_files = true; message TestCachedFieldSizeMessage { - optional protobuf_unittest.TestPackedTypes proto2_child = 1; - optional proto3_unittest.TestPackedTypes proto3_child = 2; + protobuf_unittest.TestPackedTypes proto2_child = 1; + proto3_unittest.TestPackedTypes proto3_child = 2; } diff --git a/java/core/src/test/proto/com/google/protobuf/dynamic_message_test.proto b/java/core/src/test/proto/com/google/protobuf/dynamic_message_test.proto index 170e6b5bee..62466ffb38 100644 --- a/java/core/src/test/proto/com/google/protobuf/dynamic_message_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/dynamic_message_test.proto @@ -5,10 +5,11 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto2"; +edition = "2023"; package dynamic_message_test; +option features.utf8_validation = NONE; option java_package = "dynamicmessagetest"; option java_outer_classname = "DynamicMessageTestProto"; diff --git a/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto b/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto index 638ffc1d7e..d738222601 100644 --- a/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto @@ -5,12 +5,13 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto3"; +edition = "2023"; package field_presence_test; import "google/protobuf/unittest.proto"; +option features.field_presence = IMPLICIT; option java_package = "com.google.protobuf"; option java_outer_classname = "FieldPresenceTestProto"; @@ -20,6 +21,7 @@ message TestAllTypes { BAR = 1; BAZ = 2; } + message NestedMessage { int32 value = 1; } @@ -48,7 +50,7 @@ message TestAllTypes { repeated NestedEnum repeated_nested_enum = 24; repeated NestedMessage repeated_nested_message = 25; repeated protobuf_unittest.TestRequired repeated_proto2_message = 26; - repeated NestedEnum packed_nested_enum = 27 [packed = true]; + repeated NestedEnum packed_nested_enum = 27; } message TestOptionalFieldsOnly { diff --git a/java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto b/java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto index 0d3316444c..381423e525 100644 --- a/java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto +++ b/java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto @@ -9,15 +9,19 @@ // // A proto file with lazy fields -syntax = "proto2"; +edition = "2023"; package protobuf_unittest; +option features.utf8_validation = NONE; + message LazyMessageLite { - optional int32 num = 1; - optional int32 num_with_default = 2 [default = 421]; - optional LazyInnerMessageLite inner = 3 [lazy = true]; - repeated LazyInnerMessageLite repeated_inner = 4 ; + int32 num = 1; + int32 num_with_default = 2 [default = 421]; + + LazyInnerMessageLite inner = 3 [lazy = true]; + + repeated LazyInnerMessageLite repeated_inner = 4; oneof oneof_field { int32 oneof_num = 5; @@ -26,21 +30,23 @@ message LazyMessageLite { } message LazyInnerMessageLite { - optional int32 num = 1; - optional int32 num_with_default = 2 [default = 42]; - optional LazyNestedInnerMessageLite nested = 3 [lazy = true]; + int32 num = 1; + int32 num_with_default = 2 [default = 42]; + + LazyNestedInnerMessageLite nested = 3 [lazy = true]; extensions 1000 to max; } message LazyExtension { extend LazyInnerMessageLite { - optional LazyExtension extension = 1000; + LazyExtension extension = 1000; } - optional string name = 1; + + string name = 1; } message LazyNestedInnerMessageLite { - optional int32 num = 1; - optional int32 num_with_default = 2 [default = 4]; + int32 num = 1; + int32 num_with_default = 2 [default = 4]; } diff --git a/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto b/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto index 3dabb16332..a0c6f3c7ab 100644 --- a/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto +++ b/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto @@ -7,10 +7,11 @@ // Author: pbogle@google.com (Phil Bogle) -syntax = "proto2"; +edition = "2023"; package protobuf_unittest.lite_equals_and_hash; +option features.utf8_validation = NONE; message TestOneofEquals { oneof oneof_field { @@ -20,15 +21,18 @@ message TestOneofEquals { } message Foo { - optional int32 value = 1; + int32 value = 1; repeated Bar bar = 2; map my_map = 3; + oneof Single { sint64 sint64 = 4; - // LINT: ALLOW_GROUPS - group MyGroup = 5 { - optional int32 value = 1; - } + MyGroup mygroup = 5 [features.message_encoding = DELIMITED]; + } + + // LINT: ALLOW_GROUPS + message MyGroup { + int32 value = 1; } extensions 100 to max; @@ -36,25 +40,27 @@ message Foo { message Bar { extend Foo { - optional Bar foo_ext = 100; + Bar foo_ext = 100; } - optional string name = 1; + string name = 1; } message BarPrime { - optional string name = 1; + string name = 1; } message Empty {} extend Foo { - optional int32 varint = 101; - optional fixed32 fixed32 = 102; - optional fixed64 fixed64 = 103; - optional group MyGroup = 104 { - optional string group_value = 1; - } + int32 varint = 101; + fixed32 fixed32 = 102; + fixed64 fixed64 = 103; + MyGroup mygroup = 104 [features.message_encoding = DELIMITED]; +} + +message MyGroup { + string group_value = 1; } message TestRecursiveOneof { diff --git a/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto b/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto index fb5320d84c..ca551699e7 100644 --- a/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto @@ -5,18 +5,21 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto2"; +edition = "2023"; package map_for_proto2_lite_test; +option features.enum_type = CLOSED; +option features.utf8_validation = NONE; option java_outer_classname = "MapForProto2TestProto"; option optimize_for = LITE_RUNTIME; option java_package = "map_lite_test"; message TestMap { message MessageValue { - optional int32 value = 1; + int32 value = 1; } + enum EnumValue { FOO = 0; BAR = 1; @@ -32,8 +35,9 @@ message TestMap { map string_to_int32_field = 6; message MessageWithRequiredFields { - required int32 value = 1; + int32 value = 1 [features.field_presence = LEGACY_REQUIRED]; } + map required_message_map = 11; } @@ -46,7 +50,7 @@ message TestUnknownEnumValue { // Test that the maps initialization code works correctly when the map field // references the containing message. message TestRecursiveMap { - optional int32 value = 1; + int32 value = 1; map recursive_map_field = 2; } @@ -54,14 +58,19 @@ message TestRecursiveMap { message BizarroTestMap { // same key type, different value map int32_to_int32_field = 1; + // different key and value types map int32_to_string_field = 2; + // different key types, same value map int32_to_bytes_field = 3; + // different key and value types map int32_to_enum_field = 4; + // different key and value types map int32_to_message_field = 5; + // same key type, different value map string_to_int32_field = 6; } @@ -77,11 +86,14 @@ message ReservedAsMapField { map class = 4; map int = 5; map void = 6; + // These are also proto keywords map string = 7; map package = 8; + // Most recent Java reserved word map enum = 9; + // null is not a 'reserved word' per se but as a literal needs similar care map null = 10; } @@ -91,17 +103,21 @@ message ReservedAsMapFieldWithEnumValue { A = 0; B = 1; } + map if = 1; map const = 2; map private = 3; map class = 4; map int = 5; map void = 6; + // These are also proto keywords map string = 7; map package = 8; + // Most recent Java reserved word map enum = 9; + // null is not a 'reserved word' per se but as a literal needs similar care map null = 10; } diff --git a/java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto b/java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto index 90d17cf516..f5b989d382 100644 --- a/java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto @@ -5,17 +5,20 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto2"; +edition = "2023"; package map_for_proto2_test; +option features.enum_type = CLOSED; +option features.utf8_validation = NONE; option java_package = "map_test"; option java_outer_classname = "MapForProto2TestProto"; message TestMap { message MessageValue { - optional int32 value = 1; + int32 value = 1; } + enum EnumValue { FOO = 0; BAR = 1; @@ -31,8 +34,9 @@ message TestMap { map string_to_int32_field = 6; message MessageWithRequiredFields { - required int32 value = 1; + int32 value = 1 [features.field_presence = LEGACY_REQUIRED]; } + map required_message_map = 11; } @@ -45,7 +49,7 @@ message TestUnknownEnumValue { // Test that the maps initialization code works correctly when the map field // references the containing message. message TestRecursiveMap { - optional int32 value = 1; + int32 value = 1; map recursive_map_field = 2; } @@ -53,14 +57,19 @@ message TestRecursiveMap { message BizarroTestMap { // same key type, different value map int32_to_int32_field = 1; + // different key and value types map int32_to_string_field = 2; + // different key types, same value map int32_to_bytes_field = 3; + // different key and value types map int32_to_enum_field = 4; + // different key and value types map int32_to_message_field = 5; + // same key type, different value map string_to_int32_field = 6; } @@ -76,11 +85,14 @@ message ReservedAsMapField { map class = 4; map int = 5; map void = 6; + // These are also proto keywords map string = 7; map package = 8; + // Most recent Java reserved word map enum = 9; + // null is not a 'reserved word' per se but as a literal needs similar care map null = 10; } @@ -90,17 +102,21 @@ message ReservedAsMapFieldWithEnumValue { A = 0; B = 1; } + map if = 1; map const = 2; map private = 3; map class = 4; map int = 5; map void = 6; + // These are also proto keywords map string = 7; map package = 8; + // Most recent Java reserved word map enum = 9; + // null is not a 'reserved word' per se but as a literal needs similar care map null = 10; } diff --git a/java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto b/java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto index b816d94ea5..9683c01ebe 100644 --- a/java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto @@ -14,10 +14,11 @@ // a. getDescriptor() is called on another message in the same file. // b. use protobuf reflection to access the map field. // The symptom is a NullPointerException being thrown. -syntax = "proto2"; +edition = "2023"; package map_test; +option features.utf8_validation = NONE; option java_package = "map_test"; option java_outer_classname = "MapInitializationOrderTest"; option java_multiple_files = true; @@ -27,11 +28,12 @@ option java_multiple_files = true; message Message1 { map map_field = 1; + extensions 1000 to max; } extend Message1 { - optional Message1 recursive_extension = 1001; + Message1 recursive_extension = 1001; } message RedactAllTypes {} diff --git a/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto b/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto index 8496257654..610bef8668 100644 --- a/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto @@ -5,10 +5,12 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto3"; +edition = "2023"; package map_lite_test; +option features.field_presence = IMPLICIT; + option optimize_for = LITE_RUNTIME; option java_package = "map_lite_test"; option java_outer_classname = "MapTestProto"; @@ -17,6 +19,7 @@ message TestMap { message MessageValue { int32 value = 1; } + enum EnumValue { FOO = 0; BAR = 1; @@ -45,14 +48,19 @@ message TestOnChangeEventPropagation { message BizarroTestMap { // same key type, different value map int32_to_int32_field = 1; + // different key and value types map int32_to_string_field = 2; + // different key types, same value map int32_to_bytes_field = 3; + // different key and value types map int32_to_enum_field = 4; + // different key and value types map int32_to_message_field = 5; + // same key type, different value map string_to_int32_field = 6; } @@ -68,11 +76,14 @@ message ReservedAsMapField { map class = 4; map int = 5; map void = 6; + // These are also proto keywords map string = 7; map package = 8; + // Most recent Java reserved word map enum = 9; + // null is not a 'reserved word' per se but as a literal needs similar care map null = 10; } @@ -82,22 +93,26 @@ message ReservedAsMapFieldWithEnumValue { A = 0; B = 1; } + map if = 1; map const = 2; map private = 3; map class = 4; map int = 5; map void = 6; + // These are also proto keywords map string = 7; map package = 8; + // Most recent Java reserved word map enum = 9; + // null is not a 'reserved word' per se but as a literal needs similar care map null = 10; } // https://github.com/protocolbuffers/protobuf/issues/9785 message MapContainer { - map my_map = 1; + map my_map = 1; } diff --git a/java/core/src/test/proto/com/google/protobuf/map_test.proto b/java/core/src/test/proto/com/google/protobuf/map_test.proto index f9d069bb74..4d1ac677e6 100644 --- a/java/core/src/test/proto/com/google/protobuf/map_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/map_test.proto @@ -5,10 +5,12 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto3"; +edition = "2023"; package map_test; +option features.field_presence = IMPLICIT; + option java_package = "map_test"; option java_outer_classname = "MapTestProto"; @@ -16,6 +18,7 @@ message TestMap { message MessageValue { int32 value = 1; } + enum EnumValue { FOO = 0; BAR = 1; @@ -44,14 +47,19 @@ message TestOnChangeEventPropagation { message BizarroTestMap { // same key type, different value map int32_to_int32_field = 1; + // different key and value types map int32_to_string_field = 2; + // different key types, same value map int32_to_bytes_field = 3; + // different key and value types map int32_to_enum_field = 4; + // different key and value types map int32_to_message_field = 5; + // same key type, different value map string_to_int32_field = 6; } @@ -67,11 +75,14 @@ message ReservedAsMapField { map class = 4; map int = 5; map void = 6; + // These are also proto keywords map string = 7; map package = 8; + // Most recent Java reserved word map enum = 9; + // null is not a 'reserved word' per se but as a literal needs similar care map null = 10; } @@ -81,22 +92,26 @@ message ReservedAsMapFieldWithEnumValue { A = 0; B = 1; } + map if = 1; map const = 2; map private = 3; map class = 4; map int = 5; map void = 6; + // These are also proto keywords map string = 7; map package = 8; + // Most recent Java reserved word map enum = 9; + // null is not a 'reserved word' per se but as a literal needs similar care map null = 10; } // https://github.com/protocolbuffers/protobuf/issues/9785 message MapContainer { - map my_map = 1; + map my_map = 1; } diff --git a/java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto b/java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto index baadf06164..57ae5fed25 100644 --- a/java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto @@ -9,7 +9,7 @@ // // A proto file which tests the java_multiple_files option. -syntax = "proto2"; +edition = "2023"; // Some generic_services option(s) added automatically. // See: http://go/proto2-generic-services-default @@ -18,29 +18,33 @@ package protobuf_unittest; import "google/protobuf/descriptor.proto"; import "google/protobuf/unittest.proto"; +option features.enum_type = CLOSED; option java_generic_services = true; // auto-added option java_multiple_files = true; option java_outer_classname = "MultipleFilesTestProto"; message MessageWithNoOuter { message NestedMessage { - optional int32 i = 1; + int32 i = 1; } + enum NestedEnum { BAZ = 3; } - optional NestedMessage nested = 1; + + NestedMessage nested = 1; repeated TestAllTypes foreign = 2; - optional NestedEnum nested_enum = 3; - optional EnumWithNoOuter foreign_enum = 4; + NestedEnum nested_enum = 3; + EnumWithNoOuter foreign_enum = 4; } extend google.protobuf.EnumValueOptions { - optional int32 enum_value_option = 7654321; + int32 enum_value_option = 7654321; } enum EnumWithNoOuter { FOO = 1 [(enum_value_option) = 12345]; + BAR = 2; } @@ -49,5 +53,5 @@ service ServiceWithNoOuter { } extend TestAllExtensions { - optional int32 extension_with_outer = 1234567; + int32 extension_with_outer = 1234567; } diff --git a/java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto b/java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto index 04a50047bc..c5ce68c1c0 100644 --- a/java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto @@ -6,8 +6,7 @@ // https://developers.google.com/open-source/licenses/bsd // Author: jonp@google.com (Jon Perlow) -// -syntax = "proto2"; +edition = "2023"; package protobuf_unittest; @@ -15,21 +14,21 @@ option java_multiple_files = true; option java_outer_classname = "NestedBuilders"; message Vehicle { - optional Engine engine = 1; + Engine engine = 1; repeated Wheel wheel = 2; } message Engine { - optional int32 cylinder = 1; - optional int32 liters = 2; - optional TimingBelt timing_belt = 3; + int32 cylinder = 1; + int32 liters = 2; + TimingBelt timing_belt = 3; } message TimingBelt { - optional int32 number_of_teeth = 1; + int32 number_of_teeth = 1; } message Wheel { - optional int32 radius = 1; - optional int32 width = 2; + int32 radius = 1; + int32 width = 2; } diff --git a/java/core/src/test/proto/com/google/protobuf/nested_extension.proto b/java/core/src/test/proto/com/google/protobuf/nested_extension.proto index ef7c56086f..1427c57276 100644 --- a/java/core/src/test/proto/com/google/protobuf/nested_extension.proto +++ b/java/core/src/test/proto/com/google/protobuf/nested_extension.proto @@ -10,7 +10,9 @@ // A proto file with nested extensions. Note that this must be defined in // a separate file to properly test the initialization of the outer class. -syntax = "proto2"; +// LINT: LEGACY_NAMES + +edition = "2023"; package protobuf_unittest; @@ -19,7 +21,7 @@ import "com/google/protobuf/non_nested_extension.proto"; message MyNestedExtension { extend MessageToBeExtended { - optional MessageToBeExtended recursiveExtension = 2; - optional int32 default = 2002; + MessageToBeExtended recursiveExtension = 2; + int32 default = 2002; } } diff --git a/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto b/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto index c409b1a3cf..c5fa560f75 100644 --- a/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto +++ b/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto @@ -11,7 +11,9 @@ // this must be defined in a separate file to properly test the initialization // of the outer class. -syntax = "proto2"; +// LINT: LEGACY_NAMES + +edition = "2023"; package protobuf_unittest; @@ -21,7 +23,7 @@ option optimize_for = LITE_RUNTIME; message MyNestedExtensionLite { extend MessageLiteToBeExtended { - optional MessageLiteToBeExtended recursiveExtensionLite = 3; - optional double private = 2004; + MessageLiteToBeExtended recursiveExtensionLite = 3; + double private = 2004; } } diff --git a/java/core/src/test/proto/com/google/protobuf/non_nested_extension.proto b/java/core/src/test/proto/com/google/protobuf/non_nested_extension.proto index 4ab97c81e4..230f561858 100644 --- a/java/core/src/test/proto/com/google/protobuf/non_nested_extension.proto +++ b/java/core/src/test/proto/com/google/protobuf/non_nested_extension.proto @@ -9,10 +9,13 @@ // // A proto file with extensions. -syntax = "proto2"; +// LINT: LEGACY_NAMES + +edition = "2023"; package protobuf_unittest; +option features.utf8_validation = NONE; message MessageToBeExtended { extensions 1 to max; @@ -21,6 +24,6 @@ message MessageToBeExtended { message MyNonNestedExtension {} extend MessageToBeExtended { - optional MyNonNestedExtension nonNestedExtension = 1; - optional string if = 2000; + MyNonNestedExtension nonNestedExtension = 1; + string if = 2000; } diff --git a/java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto b/java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto index d5051a4400..f25fb63113 100644 --- a/java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto +++ b/java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto @@ -9,7 +9,9 @@ // // A proto file with extensions for a MessageLite messages. -syntax = "proto2"; +// LINT: LEGACY_NAMES + +edition = "2023"; package protobuf_unittest; @@ -22,6 +24,6 @@ message MessageLiteToBeExtended { message MyNonNestedExtensionLite {} extend MessageLiteToBeExtended { - optional MyNonNestedExtensionLite nonNestedExtensionLite = 1; - optional bool package = 2006; + MyNonNestedExtensionLite nonNestedExtensionLite = 1; + bool package = 2006; } diff --git a/java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto b/java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto index 3020616e16..fbbc4dcc63 100644 --- a/java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto2"; +edition = "2023"; package protobuf_unittest; diff --git a/java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto b/java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto index 032716793b..3bc3c1240c 100644 --- a/java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto +++ b/java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto2"; +edition = "2023"; package protobuf_unittest; diff --git a/java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto b/java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto index f222989162..ba40da2452 100644 --- a/java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto +++ b/java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto2"; +edition = "2023"; package protobuf_unittest; @@ -15,6 +15,10 @@ message TestMessage3 { // This enum's name is the same with the default outer class name of this // proto file. It's used to test if the compiler can avoid this conflict // correctly. - enum OuterClassNameTest3 { DUMMY_VALUE = 1; } + enum OuterClassNameTest3 { + option features.enum_type = CLOSED; + + DUMMY_VALUE = 1; + } } } diff --git a/java/core/src/test/proto/com/google/protobuf/packed_field_test.proto b/java/core/src/test/proto/com/google/protobuf/packed_field_test.proto index b53b5e33b7..a522ce1a87 100644 --- a/java/core/src/test/proto/com/google/protobuf/packed_field_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/packed_field_test.proto @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto3"; +edition = "2023"; package packed_field_test; @@ -36,18 +36,45 @@ message TestAllTypes { } message TestUnpackedTypes { - repeated int32 repeated_int32 = 1 [packed = false]; - repeated int64 repeated_int64 = 2 [packed = false]; - repeated uint32 repeated_uint32 = 3 [packed = false]; - repeated uint64 repeated_uint64 = 4 [packed = false]; - repeated sint32 repeated_sint32 = 5 [packed = false]; - repeated sint64 repeated_sint64 = 6 [packed = false]; - repeated fixed32 repeated_fixed32 = 7 [packed = false]; - repeated fixed64 repeated_fixed64 = 8 [packed = false]; - repeated sfixed32 repeated_sfixed32 = 9 [packed = false]; - repeated sfixed64 repeated_sfixed64 = 10 [packed = false]; - repeated float repeated_float = 11 [packed = false]; - repeated double repeated_double = 12 [packed = false]; - repeated bool repeated_bool = 13 [packed = false]; - repeated TestAllTypes.NestedEnum repeated_nested_enum = 14 [packed = false]; + repeated int32 repeated_int32 = 1 + [features.repeated_field_encoding = EXPANDED]; + + repeated int64 repeated_int64 = 2 + [features.repeated_field_encoding = EXPANDED]; + + repeated uint32 repeated_uint32 = 3 + [features.repeated_field_encoding = EXPANDED]; + + repeated uint64 repeated_uint64 = 4 + [features.repeated_field_encoding = EXPANDED]; + + repeated sint32 repeated_sint32 = 5 + [features.repeated_field_encoding = EXPANDED]; + + repeated sint64 repeated_sint64 = 6 + [features.repeated_field_encoding = EXPANDED]; + + repeated fixed32 repeated_fixed32 = 7 + [features.repeated_field_encoding = EXPANDED]; + + repeated fixed64 repeated_fixed64 = 8 + [features.repeated_field_encoding = EXPANDED]; + + repeated sfixed32 repeated_sfixed32 = 9 + [features.repeated_field_encoding = EXPANDED]; + + repeated sfixed64 repeated_sfixed64 = 10 + [features.repeated_field_encoding = EXPANDED]; + + repeated float repeated_float = 11 + [features.repeated_field_encoding = EXPANDED]; + + repeated double repeated_double = 12 + [features.repeated_field_encoding = EXPANDED]; + + repeated bool repeated_bool = 13 + [features.repeated_field_encoding = EXPANDED]; + + repeated TestAllTypes.NestedEnum repeated_nested_enum = 14 + [features.repeated_field_encoding = EXPANDED]; } diff --git a/java/core/src/test/proto/com/google/protobuf/proto2_message.proto b/java/core/src/test/proto/com/google/protobuf/proto2_message.proto index 7b3411ef2a..c3f74c976b 100644 --- a/java/core/src/test/proto/com/google/protobuf/proto2_message.proto +++ b/java/core/src/test/proto/com/google/protobuf/proto2_message.proto @@ -6,82 +6,121 @@ // https://developers.google.com/open-source/licenses/bsd // LINT: ALLOW_GROUPS -syntax = "proto2"; +edition = "2023"; package protobuf.experimental; +option features.utf8_validation = NONE; option java_package = "com.google.protobuf.testing"; option java_outer_classname = "Proto2Testing"; message Proto2SpecialFieldName { - optional double regular_name = 1; - optional int32 cached_size = 2; - optional int64 serialized_size = 3; - optional string class = 4; + double regular_name = 1; + int32 cached_size = 2; + int64 serialized_size = 3; + string class = 4; } message Proto2Message { enum TestEnum { + option features.enum_type = CLOSED; + ZERO = 0; ONE = 1; TWO = 2; } - optional double field_double_1 = 1; - optional float field_float_2 = 2; - optional int64 field_int64_3 = 3; - optional uint64 field_uint64_4 = 4; - optional int32 field_int32_5 = 5; - optional fixed64 field_fixed64_6 = 6; - optional fixed32 field_fixed32_7 = 7; - optional bool field_bool_8 = 8; - optional string field_string_9 = 9; - optional Proto2Message field_message_10 = 10; - optional bytes field_bytes_11 = 11; - optional uint32 field_uint32_12 = 12; - optional TestEnum field_enum_13 = 13; - optional sfixed32 field_sfixed32_14 = 14; - optional sfixed64 field_sfixed64_15 = 15; - optional sint32 field_sint32_16 = 16; - optional sint64 field_sint64_17 = 17; - repeated double field_double_list_18 = 18 [packed = false]; - repeated float field_float_list_19 = 19 [packed = false]; - repeated int64 field_int64_list_20 = 20 [packed = false]; - repeated uint64 field_uint64_list_21 = 21 [packed = false]; - repeated int32 field_int32_list_22 = 22 [packed = false]; - repeated fixed64 field_fixed64_list_23 = 23 [packed = false]; - repeated fixed32 field_fixed32_list_24 = 24 [packed = false]; - repeated bool field_bool_list_25 = 25 [packed = false]; - repeated string field_string_list_26 = 26 [packed = false]; - repeated Proto2Message field_message_list_27 = 27 [packed = false]; - repeated bytes field_bytes_list_28 = 28 [packed = false]; - repeated uint32 field_uint32_list_29 = 29 [packed = false]; - repeated TestEnum field_enum_list_30 = 30 [packed = false]; - repeated sfixed32 field_sfixed32_list_31 = 31 [packed = false]; - repeated sfixed64 field_sfixed64_list_32 = 32 [packed = false]; - repeated sint32 field_sint32_list_33 = 33 [packed = false]; - repeated sint64 field_sint64_list_34 = 34 [packed = false]; - repeated double field_double_list_packed_35 = 35 [packed = true]; - repeated float field_float_list_packed_36 = 36 [packed = true]; - repeated int64 field_int64_list_packed_37 = 37 [packed = true]; - repeated uint64 field_uint64_list_packed_38 = 38 [packed = true]; - repeated int32 field_int32_list_packed_39 = 39 [packed = true]; - repeated fixed64 field_fixed64_list_packed_40 = 40 [packed = true]; - repeated fixed32 field_fixed32_list_packed_41 = 41 [packed = true]; - repeated bool field_bool_list_packed_42 = 42 [packed = true]; - repeated uint32 field_uint32_list_packed_43 = 43 [packed = true]; - repeated TestEnum field_enum_list_packed_44 = 44 [packed = true]; - repeated sfixed32 field_sfixed32_list_packed_45 = 45 [packed = true]; - repeated sfixed64 field_sfixed64_list_packed_46 = 46 [packed = true]; - repeated sint32 field_sint32_list_packed_47 = 47 [packed = true]; - repeated sint64 field_sint64_list_packed_48 = 48 [packed = true]; - optional group FieldGroup49 = 49 { - optional int32 field_int32_50 = 50; + double field_double_1 = 1; + float field_float_2 = 2; + int64 field_int64_3 = 3; + uint64 field_uint64_4 = 4; + int32 field_int32_5 = 5; + fixed64 field_fixed64_6 = 6; + fixed32 field_fixed32_7 = 7; + bool field_bool_8 = 8; + string field_string_9 = 9; + Proto2Message field_message_10 = 10; + bytes field_bytes_11 = 11; + uint32 field_uint32_12 = 12; + TestEnum field_enum_13 = 13; + sfixed32 field_sfixed32_14 = 14; + sfixed64 field_sfixed64_15 = 15; + sint32 field_sint32_16 = 16; + sint64 field_sint64_17 = 17; + repeated double field_double_list_18 = 18 + [features.repeated_field_encoding = EXPANDED]; + + repeated float field_float_list_19 = 19 + [features.repeated_field_encoding = EXPANDED]; + + repeated int64 field_int64_list_20 = 20 + [features.repeated_field_encoding = EXPANDED]; + + repeated uint64 field_uint64_list_21 = 21 + [features.repeated_field_encoding = EXPANDED]; + + repeated int32 field_int32_list_22 = 22 + [features.repeated_field_encoding = EXPANDED]; + + repeated fixed64 field_fixed64_list_23 = 23 + [features.repeated_field_encoding = EXPANDED]; + + repeated fixed32 field_fixed32_list_24 = 24 + [features.repeated_field_encoding = EXPANDED]; + + repeated bool field_bool_list_25 = 25 + [features.repeated_field_encoding = EXPANDED]; + + repeated string field_string_list_26 = 26; + repeated Proto2Message field_message_list_27 = 27; + repeated bytes field_bytes_list_28 = 28; + repeated uint32 field_uint32_list_29 = 29 + [features.repeated_field_encoding = EXPANDED]; + + repeated TestEnum field_enum_list_30 = 30 + [features.repeated_field_encoding = EXPANDED]; + + repeated sfixed32 field_sfixed32_list_31 = 31 + [features.repeated_field_encoding = EXPANDED]; + + repeated sfixed64 field_sfixed64_list_32 = 32 + [features.repeated_field_encoding = EXPANDED]; + + repeated sint32 field_sint32_list_33 = 33 + [features.repeated_field_encoding = EXPANDED]; + + repeated sint64 field_sint64_list_34 = 34 + [features.repeated_field_encoding = EXPANDED]; + + repeated double field_double_list_packed_35 = 35; + repeated float field_float_list_packed_36 = 36; + repeated int64 field_int64_list_packed_37 = 37; + repeated uint64 field_uint64_list_packed_38 = 38; + repeated int32 field_int32_list_packed_39 = 39; + repeated fixed64 field_fixed64_list_packed_40 = 40; + repeated fixed32 field_fixed32_list_packed_41 = 41; + repeated bool field_bool_list_packed_42 = 42; + repeated uint32 field_uint32_list_packed_43 = 43; + repeated TestEnum field_enum_list_packed_44 = 44; + repeated sfixed32 field_sfixed32_list_packed_45 = 45; + repeated sfixed64 field_sfixed64_list_packed_46 = 46; + repeated sint32 field_sint32_list_packed_47 = 47; + repeated sint64 field_sint64_list_packed_48 = 48; + + message FieldGroup49 { + int32 field_int32_50 = 50; } - repeated group FieldGroupList51 = 51 { - optional int32 field_int32_52 = 52; + + FieldGroup49 fieldgroup49 = 49 [features.message_encoding = DELIMITED]; + + message FieldGroupList51 { + int32 field_int32_52 = 52; } + + repeated FieldGroupList51 fieldgrouplist51 = 51 + [features.message_encoding = DELIMITED]; + oneof test_oneof { double field_double_53 = 53; float field_float_54 = 54; @@ -99,35 +138,75 @@ message Proto2Message { sfixed64 field_sfixed64_66 = 66; sint32 field_sint32_67 = 67; sint64 field_sint64_68 = 68; - group FieldGroup69 = 69 { - optional int32 field_int32_70 = 70; - } + FieldGroup69 fieldgroup69 = 69 [features.message_encoding = DELIMITED]; + } + + message FieldGroup69 { + int32 field_int32_70 = 70; } message RequiredNestedMessage { - optional int32 value = 1; + int32 value = 1; } - required double field_required_double_71 = 71; - required float field_required_float_72 = 72; - required int64 field_required_int64_73 = 73; - required uint64 field_required_uint64_74 = 74; - required int32 field_required_int32_75 = 75; - required fixed64 field_required_fixed64_76 = 76; - required fixed32 field_required_fixed32_77 = 77; - required bool field_required_bool_78 = 78; - required string field_required_string_79 = 79; - required RequiredNestedMessage field_required_message_80 = 80; - required bytes field_required_bytes_81 = 81; - required uint32 field_required_uint32_82 = 82; - required TestEnum field_required_enum_83 = 83; - required sfixed32 field_required_sfixed32_84 = 84; - required sfixed64 field_required_sfixed64_85 = 85; - required sint32 field_required_sint32_86 = 86; - required sint64 field_required_sint64_87 = 87; - required group FieldRequiredGroup88 = 88 { - optional int32 field_int32_89 = 89; + double field_required_double_71 = 71 + [features.field_presence = LEGACY_REQUIRED]; + + float field_required_float_72 = 72 + [features.field_presence = LEGACY_REQUIRED]; + + int64 field_required_int64_73 = 73 + [features.field_presence = LEGACY_REQUIRED]; + + uint64 field_required_uint64_74 = 74 + [features.field_presence = LEGACY_REQUIRED]; + + int32 field_required_int32_75 = 75 + [features.field_presence = LEGACY_REQUIRED]; + + fixed64 field_required_fixed64_76 = 76 + [features.field_presence = LEGACY_REQUIRED]; + + fixed32 field_required_fixed32_77 = 77 + [features.field_presence = LEGACY_REQUIRED]; + + bool field_required_bool_78 = 78 [features.field_presence = LEGACY_REQUIRED]; + + string field_required_string_79 = 79 + [features.field_presence = LEGACY_REQUIRED]; + + RequiredNestedMessage field_required_message_80 = 80 + [features.field_presence = LEGACY_REQUIRED]; + + bytes field_required_bytes_81 = 81 + [features.field_presence = LEGACY_REQUIRED]; + + uint32 field_required_uint32_82 = 82 + [features.field_presence = LEGACY_REQUIRED]; + + TestEnum field_required_enum_83 = 83 + [features.field_presence = LEGACY_REQUIRED]; + + sfixed32 field_required_sfixed32_84 = 84 + [features.field_presence = LEGACY_REQUIRED]; + + sfixed64 field_required_sfixed64_85 = 85 + [features.field_presence = LEGACY_REQUIRED]; + + sint32 field_required_sint32_86 = 86 + [features.field_presence = LEGACY_REQUIRED]; + + sint64 field_required_sint64_87 = 87 + [features.field_presence = LEGACY_REQUIRED]; + + message FieldRequiredGroup88 { + int32 field_int32_89 = 89; } + + FieldRequiredGroup88 fieldrequiredgroup88 = 88 [ + features.field_presence = LEGACY_REQUIRED, + features.message_encoding = DELIMITED + ]; } message Proto2Empty {} @@ -137,65 +216,94 @@ message Proto2MessageWithExtensions { } extend Proto2MessageWithExtensions { - optional double field_double_1 = 1; - optional float field_float_2 = 2; - optional int64 field_int64_3 = 3; - optional uint64 field_uint64_4 = 4; - optional int32 field_int32_5 = 5; - optional fixed64 field_fixed64_6 = 6; - optional fixed32 field_fixed32_7 = 7; - optional bool field_bool_8 = 8; - optional string field_string_9 = 9; - optional Proto2Message field_message_10 = 10; - optional bytes field_bytes_11 = 11; - optional uint32 field_uint32_12 = 12; - optional Proto2Message.TestEnum field_enum_13 = 13; - optional sfixed32 field_sfixed32_14 = 14; - optional sfixed64 field_sfixed64_15 = 15; - optional sint32 field_sint32_16 = 16; - optional sint64 field_sint64_17 = 17; - - repeated double field_double_list_18 = 18 [packed = false]; - repeated float field_float_list_19 = 19 [packed = false]; - repeated int64 field_int64_list_20 = 20 [packed = false]; - repeated uint64 field_uint64_list_21 = 21 [packed = false]; - repeated int32 field_int32_list_22 = 22 [packed = false]; - repeated fixed64 field_fixed64_list_23 = 23 [packed = false]; - repeated fixed32 field_fixed32_list_24 = 24 [packed = false]; - repeated bool field_bool_list_25 = 25 [packed = false]; - repeated string field_string_list_26 = 26 [packed = false]; - repeated Proto2Message field_message_list_27 = 27 [packed = false]; - repeated bytes field_bytes_list_28 = 28 [packed = false]; - repeated uint32 field_uint32_list_29 = 29 [packed = false]; - repeated Proto2Message.TestEnum field_enum_list_30 = 30 [packed = false]; - repeated sfixed32 field_sfixed32_list_31 = 31 [packed = false]; - repeated sfixed64 field_sfixed64_list_32 = 32 [packed = false]; - repeated sint32 field_sint32_list_33 = 33 [packed = false]; - repeated sint64 field_sint64_list_34 = 34 [packed = false]; - - repeated double field_double_list_packed_35 = 35 [packed = true]; - repeated float field_float_list_packed_36 = 36 [packed = true]; - repeated int64 field_int64_list_packed_37 = 37 [packed = true]; - repeated uint64 field_uint64_list_packed_38 = 38 [packed = true]; - repeated int32 field_int32_list_packed_39 = 39 [packed = true]; - repeated fixed64 field_fixed64_list_packed_40 = 40 [packed = true]; - repeated fixed32 field_fixed32_list_packed_41 = 41 [packed = true]; - repeated bool field_bool_list_packed_42 = 42 [packed = true]; - repeated uint32 field_uint32_list_packed_43 = 43 [packed = true]; - repeated Proto2Message.TestEnum field_enum_list_packed_44 = 44 - [packed = true]; - repeated sfixed32 field_sfixed32_list_packed_45 = 45 [packed = true]; - repeated sfixed64 field_sfixed64_list_packed_46 = 46 [packed = true]; - repeated sint32 field_sint32_list_packed_47 = 47 [packed = true]; - repeated sint64 field_sint64_list_packed_48 = 48 [packed = true]; - - optional group FieldGroup49 = 49 { - optional int32 field_int32_50 = 50; - } + double field_double_1 = 1; + float field_float_2 = 2; + int64 field_int64_3 = 3; + uint64 field_uint64_4 = 4; + int32 field_int32_5 = 5; + fixed64 field_fixed64_6 = 6; + fixed32 field_fixed32_7 = 7; + bool field_bool_8 = 8; + string field_string_9 = 9; + Proto2Message field_message_10 = 10; + bytes field_bytes_11 = 11; + uint32 field_uint32_12 = 12; + Proto2Message.TestEnum field_enum_13 = 13; + sfixed32 field_sfixed32_14 = 14; + sfixed64 field_sfixed64_15 = 15; + sint32 field_sint32_16 = 16; + sint64 field_sint64_17 = 17; + repeated double field_double_list_18 = 18 + [features.repeated_field_encoding = EXPANDED]; - repeated group FieldGroupList51 = 51 { - optional int32 field_int32_52 = 52; - } + repeated float field_float_list_19 = 19 + [features.repeated_field_encoding = EXPANDED]; + + repeated int64 field_int64_list_20 = 20 + [features.repeated_field_encoding = EXPANDED]; + + repeated uint64 field_uint64_list_21 = 21 + [features.repeated_field_encoding = EXPANDED]; + + repeated int32 field_int32_list_22 = 22 + [features.repeated_field_encoding = EXPANDED]; + + repeated fixed64 field_fixed64_list_23 = 23 + [features.repeated_field_encoding = EXPANDED]; + + repeated fixed32 field_fixed32_list_24 = 24 + [features.repeated_field_encoding = EXPANDED]; + + repeated bool field_bool_list_25 = 25 + [features.repeated_field_encoding = EXPANDED]; + + repeated string field_string_list_26 = 26; + repeated Proto2Message field_message_list_27 = 27; + repeated bytes field_bytes_list_28 = 28; + repeated uint32 field_uint32_list_29 = 29 + [features.repeated_field_encoding = EXPANDED]; + + repeated Proto2Message.TestEnum field_enum_list_30 = 30 + [features.repeated_field_encoding = EXPANDED]; + + repeated sfixed32 field_sfixed32_list_31 = 31 + [features.repeated_field_encoding = EXPANDED]; + + repeated sfixed64 field_sfixed64_list_32 = 32 + [features.repeated_field_encoding = EXPANDED]; + + repeated sint32 field_sint32_list_33 = 33 + [features.repeated_field_encoding = EXPANDED]; + + repeated sint64 field_sint64_list_34 = 34 + [features.repeated_field_encoding = EXPANDED]; + + repeated double field_double_list_packed_35 = 35; + repeated float field_float_list_packed_36 = 36; + repeated int64 field_int64_list_packed_37 = 37; + repeated uint64 field_uint64_list_packed_38 = 38; + repeated int32 field_int32_list_packed_39 = 39; + repeated fixed64 field_fixed64_list_packed_40 = 40; + repeated fixed32 field_fixed32_list_packed_41 = 41; + repeated bool field_bool_list_packed_42 = 42; + repeated uint32 field_uint32_list_packed_43 = 43; + repeated Proto2Message.TestEnum field_enum_list_packed_44 = 44; + repeated sfixed32 field_sfixed32_list_packed_45 = 45; + repeated sfixed64 field_sfixed64_list_packed_46 = 46; + repeated sint32 field_sint32_list_packed_47 = 47; + repeated sint64 field_sint64_list_packed_48 = 48; + FieldGroup49 fieldgroup49 = 49 [features.message_encoding = DELIMITED]; + + repeated FieldGroupList51 fieldgrouplist51 = 51 + [features.message_encoding = DELIMITED]; +} + +message FieldGroup49 { + int32 field_int32_50 = 50; +} + +message FieldGroupList51 { + int32 field_int32_52 = 52; } message Proto2MessageWithMaps { diff --git a/java/core/src/test/proto/com/google/protobuf/proto2_message_lite.proto b/java/core/src/test/proto/com/google/protobuf/proto2_message_lite.proto index 14930bb019..d903d89c88 100644 --- a/java/core/src/test/proto/com/google/protobuf/proto2_message_lite.proto +++ b/java/core/src/test/proto/com/google/protobuf/proto2_message_lite.proto @@ -6,75 +6,114 @@ // https://developers.google.com/open-source/licenses/bsd // LINT: ALLOW_GROUPS -syntax = "proto2"; +edition = "2023"; package protobuf.experimental.lite; +option features.utf8_validation = NONE; option java_package = "com.google.protobuf.testing"; option java_outer_classname = "Proto2TestingLite"; message Proto2MessageLite { enum TestEnum { + option features.enum_type = CLOSED; + ZERO = 0; ONE = 1; TWO = 2; } - optional double field_double_1 = 1; - optional float field_float_2 = 2; - optional int64 field_int64_3 = 3; - optional uint64 field_uint64_4 = 4; - optional int32 field_int32_5 = 5; - optional fixed64 field_fixed64_6 = 6; - optional fixed32 field_fixed32_7 = 7; - optional bool field_bool_8 = 8; - optional string field_string_9 = 9; - optional Proto2MessageLite field_message_10 = 10; - optional bytes field_bytes_11 = 11; - optional uint32 field_uint32_12 = 12; - optional TestEnum field_enum_13 = 13; - optional sfixed32 field_sfixed32_14 = 14; - optional sfixed64 field_sfixed64_15 = 15; - optional sint32 field_sint32_16 = 16; - optional sint64 field_sint64_17 = 17; - repeated double field_double_list_18 = 18 [packed = false]; - repeated float field_float_list_19 = 19 [packed = false]; - repeated int64 field_int64_list_20 = 20 [packed = false]; - repeated uint64 field_uint64_list_21 = 21 [packed = false]; - repeated int32 field_int32_list_22 = 22 [packed = false]; - repeated fixed64 field_fixed64_list_23 = 23 [packed = false]; - repeated fixed32 field_fixed32_list_24 = 24 [packed = false]; - repeated bool field_bool_list_25 = 25 [packed = false]; - repeated string field_string_list_26 = 26 [packed = false]; - repeated Proto2MessageLite field_message_list_27 = 27 [packed = false]; - repeated bytes field_bytes_list_28 = 28 [packed = false]; - repeated uint32 field_uint32_list_29 = 29 [packed = false]; - repeated TestEnum field_enum_list_30 = 30 [packed = false]; - repeated sfixed32 field_sfixed32_list_31 = 31 [packed = false]; - repeated sfixed64 field_sfixed64_list_32 = 32 [packed = false]; - repeated sint32 field_sint32_list_33 = 33 [packed = false]; - repeated sint64 field_sint64_list_34 = 34 [packed = false]; - repeated double field_double_list_packed_35 = 35 [packed = true]; - repeated float field_float_list_packed_36 = 36 [packed = true]; - repeated int64 field_int64_list_packed_37 = 37 [packed = true]; - repeated uint64 field_uint64_list_packed_38 = 38 [packed = true]; - repeated int32 field_int32_list_packed_39 = 39 [packed = true]; - repeated fixed64 field_fixed64_list_packed_40 = 40 [packed = true]; - repeated fixed32 field_fixed32_list_packed_41 = 41 [packed = true]; - repeated bool field_bool_list_packed_42 = 42 [packed = true]; - repeated uint32 field_uint32_list_packed_43 = 43 [packed = true]; - repeated TestEnum field_enum_list_packed_44 = 44 [packed = true]; - repeated sfixed32 field_sfixed32_list_packed_45 = 45 [packed = true]; - repeated sfixed64 field_sfixed64_list_packed_46 = 46 [packed = true]; - repeated sint32 field_sint32_list_packed_47 = 47 [packed = true]; - repeated sint64 field_sint64_list_packed_48 = 48 [packed = true]; - optional group FieldGroup49 = 49 { - optional int32 field_int32_50 = 50; + double field_double_1 = 1; + float field_float_2 = 2; + int64 field_int64_3 = 3; + uint64 field_uint64_4 = 4; + int32 field_int32_5 = 5; + fixed64 field_fixed64_6 = 6; + fixed32 field_fixed32_7 = 7; + bool field_bool_8 = 8; + string field_string_9 = 9; + Proto2MessageLite field_message_10 = 10; + bytes field_bytes_11 = 11; + uint32 field_uint32_12 = 12; + TestEnum field_enum_13 = 13; + sfixed32 field_sfixed32_14 = 14; + sfixed64 field_sfixed64_15 = 15; + sint32 field_sint32_16 = 16; + sint64 field_sint64_17 = 17; + repeated double field_double_list_18 = 18 + [features.repeated_field_encoding = EXPANDED]; + + repeated float field_float_list_19 = 19 + [features.repeated_field_encoding = EXPANDED]; + + repeated int64 field_int64_list_20 = 20 + [features.repeated_field_encoding = EXPANDED]; + + repeated uint64 field_uint64_list_21 = 21 + [features.repeated_field_encoding = EXPANDED]; + + repeated int32 field_int32_list_22 = 22 + [features.repeated_field_encoding = EXPANDED]; + + repeated fixed64 field_fixed64_list_23 = 23 + [features.repeated_field_encoding = EXPANDED]; + + repeated fixed32 field_fixed32_list_24 = 24 + [features.repeated_field_encoding = EXPANDED]; + + repeated bool field_bool_list_25 = 25 + [features.repeated_field_encoding = EXPANDED]; + + repeated string field_string_list_26 = 26; + repeated Proto2MessageLite field_message_list_27 = 27; + repeated bytes field_bytes_list_28 = 28; + repeated uint32 field_uint32_list_29 = 29 + [features.repeated_field_encoding = EXPANDED]; + + repeated TestEnum field_enum_list_30 = 30 + [features.repeated_field_encoding = EXPANDED]; + + repeated sfixed32 field_sfixed32_list_31 = 31 + [features.repeated_field_encoding = EXPANDED]; + + repeated sfixed64 field_sfixed64_list_32 = 32 + [features.repeated_field_encoding = EXPANDED]; + + repeated sint32 field_sint32_list_33 = 33 + [features.repeated_field_encoding = EXPANDED]; + + repeated sint64 field_sint64_list_34 = 34 + [features.repeated_field_encoding = EXPANDED]; + + repeated double field_double_list_packed_35 = 35; + repeated float field_float_list_packed_36 = 36; + repeated int64 field_int64_list_packed_37 = 37; + repeated uint64 field_uint64_list_packed_38 = 38; + repeated int32 field_int32_list_packed_39 = 39; + repeated fixed64 field_fixed64_list_packed_40 = 40; + repeated fixed32 field_fixed32_list_packed_41 = 41; + repeated bool field_bool_list_packed_42 = 42; + repeated uint32 field_uint32_list_packed_43 = 43; + repeated TestEnum field_enum_list_packed_44 = 44; + repeated sfixed32 field_sfixed32_list_packed_45 = 45; + repeated sfixed64 field_sfixed64_list_packed_46 = 46; + repeated sint32 field_sint32_list_packed_47 = 47; + repeated sint64 field_sint64_list_packed_48 = 48; + + message FieldGroup49 { + int32 field_int32_50 = 50; } - repeated group FieldGroupList51 = 51 { - optional int32 field_int32_52 = 52; + + FieldGroup49 fieldgroup49 = 49 [features.message_encoding = DELIMITED]; + + message FieldGroupList51 { + int32 field_int32_52 = 52; } + + repeated FieldGroupList51 fieldgrouplist51 = 51 + [features.message_encoding = DELIMITED]; + oneof test_oneof { double field_double_53 = 53; float field_float_54 = 54; @@ -92,35 +131,75 @@ message Proto2MessageLite { sfixed64 field_sfixed64_66 = 66; sint32 field_sint32_67 = 67; sint64 field_sint64_68 = 68; - group FieldGroup69 = 69 { - optional int32 field_int32_70 = 70; - } + FieldGroup69 fieldgroup69 = 69 [features.message_encoding = DELIMITED]; + } + + message FieldGroup69 { + int32 field_int32_70 = 70; } message RequiredNestedMessage { - optional int32 value = 1; + int32 value = 1; } - required double field_required_double_71 = 71; - required float field_required_float_72 = 72; - required int64 field_required_int64_73 = 73; - required uint64 field_required_uint64_74 = 74; - required int32 field_required_int32_75 = 75; - required fixed64 field_required_fixed64_76 = 76; - required fixed32 field_required_fixed32_77 = 77; - required bool field_required_bool_78 = 78; - required string field_required_string_79 = 79; - required RequiredNestedMessage field_required_message_80 = 80; - required bytes field_required_bytes_81 = 81; - required uint32 field_required_uint32_82 = 82; - required TestEnum field_required_enum_83 = 83; - required sfixed32 field_required_sfixed32_84 = 84; - required sfixed64 field_required_sfixed64_85 = 85; - required sint32 field_required_sint32_86 = 86; - required sint64 field_required_sint64_87 = 87; - required group FieldRequiredGroup88 = 88 { - optional int32 field_int32_89 = 89; + double field_required_double_71 = 71 + [features.field_presence = LEGACY_REQUIRED]; + + float field_required_float_72 = 72 + [features.field_presence = LEGACY_REQUIRED]; + + int64 field_required_int64_73 = 73 + [features.field_presence = LEGACY_REQUIRED]; + + uint64 field_required_uint64_74 = 74 + [features.field_presence = LEGACY_REQUIRED]; + + int32 field_required_int32_75 = 75 + [features.field_presence = LEGACY_REQUIRED]; + + fixed64 field_required_fixed64_76 = 76 + [features.field_presence = LEGACY_REQUIRED]; + + fixed32 field_required_fixed32_77 = 77 + [features.field_presence = LEGACY_REQUIRED]; + + bool field_required_bool_78 = 78 [features.field_presence = LEGACY_REQUIRED]; + + string field_required_string_79 = 79 + [features.field_presence = LEGACY_REQUIRED]; + + RequiredNestedMessage field_required_message_80 = 80 + [features.field_presence = LEGACY_REQUIRED]; + + bytes field_required_bytes_81 = 81 + [features.field_presence = LEGACY_REQUIRED]; + + uint32 field_required_uint32_82 = 82 + [features.field_presence = LEGACY_REQUIRED]; + + TestEnum field_required_enum_83 = 83 + [features.field_presence = LEGACY_REQUIRED]; + + sfixed32 field_required_sfixed32_84 = 84 + [features.field_presence = LEGACY_REQUIRED]; + + sfixed64 field_required_sfixed64_85 = 85 + [features.field_presence = LEGACY_REQUIRED]; + + sint32 field_required_sint32_86 = 86 + [features.field_presence = LEGACY_REQUIRED]; + + sint64 field_required_sint64_87 = 87 + [features.field_presence = LEGACY_REQUIRED]; + + message FieldRequiredGroup88 { + int32 field_int32_89 = 89; } + + FieldRequiredGroup88 fieldrequiredgroup88 = 88 [ + features.field_presence = LEGACY_REQUIRED, + features.message_encoding = DELIMITED + ]; } message Proto2EmptyLite {} @@ -130,65 +209,94 @@ message Proto2MessageLiteWithExtensions { } extend Proto2MessageLiteWithExtensions { - optional double field_double_1 = 1; - optional float field_float_2 = 2; - optional int64 field_int64_3 = 3; - optional uint64 field_uint64_4 = 4; - optional int32 field_int32_5 = 5; - optional fixed64 field_fixed64_6 = 6; - optional fixed32 field_fixed32_7 = 7; - optional bool field_bool_8 = 8; - optional string field_string_9 = 9; - optional Proto2MessageLite field_message_10 = 10; - optional bytes field_bytes_11 = 11; - optional uint32 field_uint32_12 = 12; - optional Proto2MessageLite.TestEnum field_enum_13 = 13; - optional sfixed32 field_sfixed32_14 = 14; - optional sfixed64 field_sfixed64_15 = 15; - optional sint32 field_sint32_16 = 16; - optional sint64 field_sint64_17 = 17; - - repeated double field_double_list_18 = 18 [packed = false]; - repeated float field_float_list_19 = 19 [packed = false]; - repeated int64 field_int64_list_20 = 20 [packed = false]; - repeated uint64 field_uint64_list_21 = 21 [packed = false]; - repeated int32 field_int32_list_22 = 22 [packed = false]; - repeated fixed64 field_fixed64_list_23 = 23 [packed = false]; - repeated fixed32 field_fixed32_list_24 = 24 [packed = false]; - repeated bool field_bool_list_25 = 25 [packed = false]; - repeated string field_string_list_26 = 26 [packed = false]; - repeated Proto2MessageLite field_message_list_27 = 27 [packed = false]; - repeated bytes field_bytes_list_28 = 28 [packed = false]; - repeated uint32 field_uint32_list_29 = 29 [packed = false]; - repeated Proto2MessageLite.TestEnum field_enum_list_30 = 30 [packed = false]; - repeated sfixed32 field_sfixed32_list_31 = 31 [packed = false]; - repeated sfixed64 field_sfixed64_list_32 = 32 [packed = false]; - repeated sint32 field_sint32_list_33 = 33 [packed = false]; - repeated sint64 field_sint64_list_34 = 34 [packed = false]; - - repeated double field_double_list_packed_35 = 35 [packed = true]; - repeated float field_float_list_packed_36 = 36 [packed = true]; - repeated int64 field_int64_list_packed_37 = 37 [packed = true]; - repeated uint64 field_uint64_list_packed_38 = 38 [packed = true]; - repeated int32 field_int32_list_packed_39 = 39 [packed = true]; - repeated fixed64 field_fixed64_list_packed_40 = 40 [packed = true]; - repeated fixed32 field_fixed32_list_packed_41 = 41 [packed = true]; - repeated bool field_bool_list_packed_42 = 42 [packed = true]; - repeated uint32 field_uint32_list_packed_43 = 43 [packed = true]; - repeated Proto2MessageLite.TestEnum field_enum_list_packed_44 = 44 - [packed = true]; - repeated sfixed32 field_sfixed32_list_packed_45 = 45 [packed = true]; - repeated sfixed64 field_sfixed64_list_packed_46 = 46 [packed = true]; - repeated sint32 field_sint32_list_packed_47 = 47 [packed = true]; - repeated sint64 field_sint64_list_packed_48 = 48 [packed = true]; - - optional group FieldGroup49 = 49 { - optional int32 field_int32_50 = 50; - } + double field_double_1 = 1; + float field_float_2 = 2; + int64 field_int64_3 = 3; + uint64 field_uint64_4 = 4; + int32 field_int32_5 = 5; + fixed64 field_fixed64_6 = 6; + fixed32 field_fixed32_7 = 7; + bool field_bool_8 = 8; + string field_string_9 = 9; + Proto2MessageLite field_message_10 = 10; + bytes field_bytes_11 = 11; + uint32 field_uint32_12 = 12; + Proto2MessageLite.TestEnum field_enum_13 = 13; + sfixed32 field_sfixed32_14 = 14; + sfixed64 field_sfixed64_15 = 15; + sint32 field_sint32_16 = 16; + sint64 field_sint64_17 = 17; + repeated double field_double_list_18 = 18 + [features.repeated_field_encoding = EXPANDED]; - repeated group FieldGroupList51 = 51 { - optional int32 field_int32_52 = 52; - } + repeated float field_float_list_19 = 19 + [features.repeated_field_encoding = EXPANDED]; + + repeated int64 field_int64_list_20 = 20 + [features.repeated_field_encoding = EXPANDED]; + + repeated uint64 field_uint64_list_21 = 21 + [features.repeated_field_encoding = EXPANDED]; + + repeated int32 field_int32_list_22 = 22 + [features.repeated_field_encoding = EXPANDED]; + + repeated fixed64 field_fixed64_list_23 = 23 + [features.repeated_field_encoding = EXPANDED]; + + repeated fixed32 field_fixed32_list_24 = 24 + [features.repeated_field_encoding = EXPANDED]; + + repeated bool field_bool_list_25 = 25 + [features.repeated_field_encoding = EXPANDED]; + + repeated string field_string_list_26 = 26; + repeated Proto2MessageLite field_message_list_27 = 27; + repeated bytes field_bytes_list_28 = 28; + repeated uint32 field_uint32_list_29 = 29 + [features.repeated_field_encoding = EXPANDED]; + + repeated Proto2MessageLite.TestEnum field_enum_list_30 = 30 + [features.repeated_field_encoding = EXPANDED]; + + repeated sfixed32 field_sfixed32_list_31 = 31 + [features.repeated_field_encoding = EXPANDED]; + + repeated sfixed64 field_sfixed64_list_32 = 32 + [features.repeated_field_encoding = EXPANDED]; + + repeated sint32 field_sint32_list_33 = 33 + [features.repeated_field_encoding = EXPANDED]; + + repeated sint64 field_sint64_list_34 = 34 + [features.repeated_field_encoding = EXPANDED]; + + repeated double field_double_list_packed_35 = 35; + repeated float field_float_list_packed_36 = 36; + repeated int64 field_int64_list_packed_37 = 37; + repeated uint64 field_uint64_list_packed_38 = 38; + repeated int32 field_int32_list_packed_39 = 39; + repeated fixed64 field_fixed64_list_packed_40 = 40; + repeated fixed32 field_fixed32_list_packed_41 = 41; + repeated bool field_bool_list_packed_42 = 42; + repeated uint32 field_uint32_list_packed_43 = 43; + repeated Proto2MessageLite.TestEnum field_enum_list_packed_44 = 44; + repeated sfixed32 field_sfixed32_list_packed_45 = 45; + repeated sfixed64 field_sfixed64_list_packed_46 = 46; + repeated sint32 field_sint32_list_packed_47 = 47; + repeated sint64 field_sint64_list_packed_48 = 48; + FieldGroup49 fieldgroup49 = 49 [features.message_encoding = DELIMITED]; + + repeated FieldGroupList51 fieldgrouplist51 = 51 + [features.message_encoding = DELIMITED]; +} + +message FieldGroup49 { + int32 field_int32_50 = 50; +} + +message FieldGroupList51 { + int32 field_int32_52 = 52; } message Proto2MessageLiteWithMaps { diff --git a/java/core/src/test/proto/com/google/protobuf/proto2_text_format_performance_test.proto b/java/core/src/test/proto/com/google/protobuf/proto2_text_format_performance_test.proto index bce621fb40..96473739b0 100644 --- a/java/core/src/test/proto/com/google/protobuf/proto2_text_format_performance_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/proto2_text_format_performance_test.proto @@ -5,15 +5,16 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto2"; +edition = "2023"; package protobuf.testing.textformat.performance.proto2; +option features.repeated_field_encoding = EXPANDED; option java_package = "com.google.protobuf.testing.textformat.performance.proto2"; option java_outer_classname = "Proto2TextFormatPerformanceProto"; message ContainsSubMessageWithRepeatedInt32 { - optional RepeatedInt32 sub_msg = 1; + RepeatedInt32 sub_msg = 1; } message RepeatedInt32 { @@ -25,5 +26,5 @@ message ContainsExtensionSubMessage { } extend ContainsExtensionSubMessage { - optional RepeatedInt32 sub_msg_ext = 1; + RepeatedInt32 sub_msg_ext = 1; } diff --git a/java/core/src/test/proto/com/google/protobuf/proto2_unknown_enum_values.proto b/java/core/src/test/proto/com/google/protobuf/proto2_unknown_enum_values.proto index bb7d9596cb..bb51b26607 100644 --- a/java/core/src/test/proto/com/google/protobuf/proto2_unknown_enum_values.proto +++ b/java/core/src/test/proto/com/google/protobuf/proto2_unknown_enum_values.proto @@ -5,10 +5,11 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto2"; +edition = "2023"; package proto2_unknown_enum_values; +option features.enum_type = CLOSED; option java_package = "com.google.protobuf"; option java_outer_classname = "Proto2UnknownEnumValuesTestProto"; @@ -19,7 +20,7 @@ enum Proto2TestEnum { } message Proto2EnumMessage { - repeated Proto2TestEnum repeated_packed_enum = 1 [packed = true]; + repeated Proto2TestEnum repeated_packed_enum = 1; } // An enum containing a subset of the values of Proto2TestEnum, to test @@ -27,11 +28,12 @@ message Proto2EnumMessage { enum Proto2TestEnumSubset { TESTENUM_SUBSET_ZERO = 0; TESTENUM_SUBSET_ONE = 1; + // No enum value with number 2. } // Test messages for packed enum, with identical field number as // Proto2Message, to test parsing unknown packed enums. message Proto2EnumMessageWithEnumSubset { - repeated Proto2TestEnumSubset repeated_packed_enum = 1 [packed = true]; + repeated Proto2TestEnumSubset repeated_packed_enum = 1; } diff --git a/java/core/src/test/proto/com/google/protobuf/proto3_message.proto b/java/core/src/test/proto/com/google/protobuf/proto3_message.proto index 9b439c0ae2..a64bce52fc 100644 --- a/java/core/src/test/proto/com/google/protobuf/proto3_message.proto +++ b/java/core/src/test/proto/com/google/protobuf/proto3_message.proto @@ -5,10 +5,11 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto3"; +edition = "2023"; package protobuf.experimental; +option features.field_presence = IMPLICIT; option java_package = "com.google.protobuf.testing"; option java_outer_classname = "Proto3Testing"; @@ -43,37 +44,72 @@ message Proto3Message { sfixed64 field_sfixed64_15 = 15; sint32 field_sint32_16 = 16; sint64 field_sint64_17 = 17; - repeated double field_double_list_18 = 18 [packed = false]; - repeated float field_float_list_19 = 19 [packed = false]; - repeated int64 field_int64_list_20 = 20 [packed = false]; - repeated uint64 field_uint64_list_21 = 21 [packed = false]; - repeated int32 field_int32_list_22 = 22 [packed = false]; - repeated fixed64 field_fixed64_list_23 = 23 [packed = false]; - repeated fixed32 field_fixed32_list_24 = 24 [packed = false]; - repeated bool field_bool_list_25 = 25 [packed = false]; - repeated string field_string_list_26 = 26 [packed = false]; - repeated Proto3Message field_message_list_27 = 27 [packed = false]; - repeated bytes field_bytes_list_28 = 28 [packed = false]; - repeated uint32 field_uint32_list_29 = 29 [packed = false]; - repeated TestEnum field_enum_list_30 = 30 [packed = false]; - repeated sfixed32 field_sfixed32_list_31 = 31 [packed = false]; - repeated sfixed64 field_sfixed64_list_32 = 32 [packed = false]; - repeated sint32 field_sint32_list_33 = 33 [packed = false]; - repeated sint64 field_sint64_list_34 = 34 [packed = false]; - repeated double field_double_list_packed_35 = 35 [packed = true]; - repeated float field_float_list_packed_36 = 36 [packed = true]; - repeated int64 field_int64_list_packed_37 = 37 [packed = true]; - repeated uint64 field_uint64_list_packed_38 = 38 [packed = true]; - repeated int32 field_int32_list_packed_39 = 39 [packed = true]; - repeated fixed64 field_fixed64_list_packed_40 = 40 [packed = true]; - repeated fixed32 field_fixed32_list_packed_41 = 41 [packed = true]; - repeated bool field_bool_list_packed_42 = 42 [packed = true]; - repeated uint32 field_uint32_list_packed_43 = 43 [packed = true]; - repeated TestEnum field_enum_list_packed_44 = 44 [packed = true]; - repeated sfixed32 field_sfixed32_list_packed_45 = 45 [packed = true]; - repeated sfixed64 field_sfixed64_list_packed_46 = 46 [packed = true]; - repeated sint32 field_sint32_list_packed_47 = 47 [packed = true]; - repeated sint64 field_sint64_list_packed_48 = 48 [packed = true]; + repeated double field_double_list_18 = 18 + [features.repeated_field_encoding = EXPANDED]; + + repeated float field_float_list_19 = 19 + [features.repeated_field_encoding = EXPANDED]; + + repeated int64 field_int64_list_20 = 20 + [features.repeated_field_encoding = EXPANDED]; + + repeated uint64 field_uint64_list_21 = 21 + [features.repeated_field_encoding = EXPANDED]; + + repeated int32 field_int32_list_22 = 22 + [features.repeated_field_encoding = EXPANDED]; + + repeated fixed64 field_fixed64_list_23 = 23 + [features.repeated_field_encoding = EXPANDED]; + + repeated fixed32 field_fixed32_list_24 = 24 + [features.repeated_field_encoding = EXPANDED]; + + repeated bool field_bool_list_25 = 25 + [features.repeated_field_encoding = EXPANDED]; + + repeated string field_string_list_26 = 26 + [features.repeated_field_encoding = EXPANDED]; + + repeated Proto3Message field_message_list_27 = 27 + [features.repeated_field_encoding = EXPANDED]; + + repeated bytes field_bytes_list_28 = 28 + [features.repeated_field_encoding = EXPANDED]; + + repeated uint32 field_uint32_list_29 = 29 + [features.repeated_field_encoding = EXPANDED]; + + repeated TestEnum field_enum_list_30 = 30 + [features.repeated_field_encoding = EXPANDED]; + + repeated sfixed32 field_sfixed32_list_31 = 31 + [features.repeated_field_encoding = EXPANDED]; + + repeated sfixed64 field_sfixed64_list_32 = 32 + [features.repeated_field_encoding = EXPANDED]; + + repeated sint32 field_sint32_list_33 = 33 + [features.repeated_field_encoding = EXPANDED]; + + repeated sint64 field_sint64_list_34 = 34 + [features.repeated_field_encoding = EXPANDED]; + + repeated double field_double_list_packed_35 = 35; + repeated float field_float_list_packed_36 = 36; + repeated int64 field_int64_list_packed_37 = 37; + repeated uint64 field_uint64_list_packed_38 = 38; + repeated int32 field_int32_list_packed_39 = 39; + repeated fixed64 field_fixed64_list_packed_40 = 40; + repeated fixed32 field_fixed32_list_packed_41 = 41; + repeated bool field_bool_list_packed_42 = 42; + repeated uint32 field_uint32_list_packed_43 = 43; + repeated TestEnum field_enum_list_packed_44 = 44; + repeated sfixed32 field_sfixed32_list_packed_45 = 45; + repeated sfixed64 field_sfixed64_list_packed_46 = 46; + repeated sint32 field_sint32_list_packed_47 = 47; + repeated sint64 field_sint64_list_packed_48 = 48; + oneof test_oneof { double field_double_53 = 53; float field_float_54 = 54; diff --git a/java/core/src/test/proto/com/google/protobuf/proto3_message_lite.proto b/java/core/src/test/proto/com/google/protobuf/proto3_message_lite.proto index 09537cb1d4..79b029cd85 100644 --- a/java/core/src/test/proto/com/google/protobuf/proto3_message_lite.proto +++ b/java/core/src/test/proto/com/google/protobuf/proto3_message_lite.proto @@ -5,10 +5,11 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto3"; +edition = "2023"; package protobuf.experimental; +option features.field_presence = IMPLICIT; option java_package = "com.google.protobuf.testing"; option java_outer_classname = "Proto3TestingLite"; @@ -36,37 +37,72 @@ message Proto3MessageLite { sfixed64 field_sfixed64_15 = 15; sint32 field_sint32_16 = 16; sint64 field_sint64_17 = 17; - repeated double field_double_list_18 = 18 [packed = false]; - repeated float field_float_list_19 = 19 [packed = false]; - repeated int64 field_int64_list_20 = 20 [packed = false]; - repeated uint64 field_uint64_list_21 = 21 [packed = false]; - repeated int32 field_int32_list_22 = 22 [packed = false]; - repeated fixed64 field_fixed64_list_23 = 23 [packed = false]; - repeated fixed32 field_fixed32_list_24 = 24 [packed = false]; - repeated bool field_bool_list_25 = 25 [packed = false]; - repeated string field_string_list_26 = 26 [packed = false]; - repeated Proto3MessageLite field_message_list_27 = 27 [packed = false]; - repeated bytes field_bytes_list_28 = 28 [packed = false]; - repeated uint32 field_uint32_list_29 = 29 [packed = false]; - repeated TestEnum field_enum_list_30 = 30 [packed = false]; - repeated sfixed32 field_sfixed32_list_31 = 31 [packed = false]; - repeated sfixed64 field_sfixed64_list_32 = 32 [packed = false]; - repeated sint32 field_sint32_list_33 = 33 [packed = false]; - repeated sint64 field_sint64_list_34 = 34 [packed = false]; - repeated double field_double_list_packed_35 = 35 [packed = true]; - repeated float field_float_list_packed_36 = 36 [packed = true]; - repeated int64 field_int64_list_packed_37 = 37 [packed = true]; - repeated uint64 field_uint64_list_packed_38 = 38 [packed = true]; - repeated int32 field_int32_list_packed_39 = 39 [packed = true]; - repeated fixed64 field_fixed64_list_packed_40 = 40 [packed = true]; - repeated fixed32 field_fixed32_list_packed_41 = 41 [packed = true]; - repeated bool field_bool_list_packed_42 = 42 [packed = true]; - repeated uint32 field_uint32_list_packed_43 = 43 [packed = true]; - repeated TestEnum field_enum_list_packed_44 = 44 [packed = true]; - repeated sfixed32 field_sfixed32_list_packed_45 = 45 [packed = true]; - repeated sfixed64 field_sfixed64_list_packed_46 = 46 [packed = true]; - repeated sint32 field_sint32_list_packed_47 = 47 [packed = true]; - repeated sint64 field_sint64_list_packed_48 = 48 [packed = true]; + repeated double field_double_list_18 = 18 + [features.repeated_field_encoding = EXPANDED]; + + repeated float field_float_list_19 = 19 + [features.repeated_field_encoding = EXPANDED]; + + repeated int64 field_int64_list_20 = 20 + [features.repeated_field_encoding = EXPANDED]; + + repeated uint64 field_uint64_list_21 = 21 + [features.repeated_field_encoding = EXPANDED]; + + repeated int32 field_int32_list_22 = 22 + [features.repeated_field_encoding = EXPANDED]; + + repeated fixed64 field_fixed64_list_23 = 23 + [features.repeated_field_encoding = EXPANDED]; + + repeated fixed32 field_fixed32_list_24 = 24 + [features.repeated_field_encoding = EXPANDED]; + + repeated bool field_bool_list_25 = 25 + [features.repeated_field_encoding = EXPANDED]; + + repeated string field_string_list_26 = 26 + [features.repeated_field_encoding = EXPANDED]; + + repeated Proto3MessageLite field_message_list_27 = 27 + [features.repeated_field_encoding = EXPANDED]; + + repeated bytes field_bytes_list_28 = 28 + [features.repeated_field_encoding = EXPANDED]; + + repeated uint32 field_uint32_list_29 = 29 + [features.repeated_field_encoding = EXPANDED]; + + repeated TestEnum field_enum_list_30 = 30 + [features.repeated_field_encoding = EXPANDED]; + + repeated sfixed32 field_sfixed32_list_31 = 31 + [features.repeated_field_encoding = EXPANDED]; + + repeated sfixed64 field_sfixed64_list_32 = 32 + [features.repeated_field_encoding = EXPANDED]; + + repeated sint32 field_sint32_list_33 = 33 + [features.repeated_field_encoding = EXPANDED]; + + repeated sint64 field_sint64_list_34 = 34 + [features.repeated_field_encoding = EXPANDED]; + + repeated double field_double_list_packed_35 = 35; + repeated float field_float_list_packed_36 = 36; + repeated int64 field_int64_list_packed_37 = 37; + repeated uint64 field_uint64_list_packed_38 = 38; + repeated int32 field_int32_list_packed_39 = 39; + repeated fixed64 field_fixed64_list_packed_40 = 40; + repeated fixed32 field_fixed32_list_packed_41 = 41; + repeated bool field_bool_list_packed_42 = 42; + repeated uint32 field_uint32_list_packed_43 = 43; + repeated TestEnum field_enum_list_packed_44 = 44; + repeated sfixed32 field_sfixed32_list_packed_45 = 45; + repeated sfixed64 field_sfixed64_list_packed_46 = 46; + repeated sint32 field_sint32_list_packed_47 = 47; + repeated sint64 field_sint64_list_packed_48 = 48; + oneof test_oneof { double field_double_53 = 53; float field_float_54 = 54; diff --git a/java/core/src/test/proto/com/google/protobuf/proto3_text_format_performance_test.proto b/java/core/src/test/proto/com/google/protobuf/proto3_text_format_performance_test.proto index 5a837fc7e8..30454fcbc4 100644 --- a/java/core/src/test/proto/com/google/protobuf/proto3_text_format_performance_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/proto3_text_format_performance_test.proto @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto3"; +edition = "2023"; package protobuf.testing.textformat.performance.proto3; @@ -13,7 +13,7 @@ option java_package = "com.google.protobuf.testing.textformat.performance.proto3 option java_outer_classname = "Proto3TextFormatPerformanceProto"; message ContainsSubMessageWithRepeatedInt32 { - optional RepeatedInt32 sub_msg = 1; + RepeatedInt32 sub_msg = 1; } message RepeatedInt32 { diff --git a/java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto b/java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto index f79521361d..5c70ed43ca 100644 --- a/java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto +++ b/java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto @@ -11,10 +11,13 @@ // though the same identifiers are used internally by the java code generator. // LINT: LEGACY_NAMES -syntax = "proto2"; +edition = "2023"; package io_protocol_tests; +option features.repeated_field_encoding = EXPANDED; +option features.utf8_validation = NONE; +option features.enum_type = CLOSED; option java_generic_services = true; // auto-added option java_package = "com.google.protobuf"; option java_outer_classname = "TestBadIdentifiersProto"; @@ -24,19 +27,19 @@ option java_outer_classname = "TestBadIdentifiersProto"; // src/google/protobuf/compiler/java/java_helpers.cc message ForbiddenWordsUnderscoreMessage { // java.lang.Object - optional bool class = 1; + bool class = 1; // com.google.protobuf.MessageLiteOrBuilder - optional bool default_instance_for_type = 2; + bool default_instance_for_type = 2; // com.google.protobuf.MessageLite - optional bool parser_for_type = 3; - optional bool serialized_size = 4; + bool parser_for_type = 3; + bool serialized_size = 4; // com.google.protobuf.MessageOrBuilder - optional bool all_fields = 5; - optional bool descriptor_for_type = 6; - optional bool initialization_error_string = 7; - optional bool unknown_fields = 8; + bool all_fields = 5; + bool descriptor_for_type = 6; + bool initialization_error_string = 7; + bool unknown_fields = 8; // obsolete. kept for backwards compatibility of generated code - optional bool cached_size = 9; + bool cached_size = 9; } // Message with field names using leading underscores that conflict with @@ -44,20 +47,20 @@ message ForbiddenWordsUnderscoreMessage { // src/google/protobuf/compiler/java/java_helpers.cc message ForbiddenWordsLeadingUnderscoreMessage { // java.lang.Object - optional bool _class = 1; + bool _class = 1; // com.google.protobuf.MessageLiteOrBuilder - optional bool _default_instance_for_type = 2; + bool _default_instance_for_type = 2; // com.google.protobuf.MessageLite - optional bool _parser_for_type = 3; - optional bool _serialized_size = 4; + bool _parser_for_type = 3; + bool _serialized_size = 4; // com.google.protobuf.MessageOrBuilder - optional bool _all_fields = 5; - optional bool _descriptor_for_type = 6; - optional bool _initialization_error_string = 7; + bool _all_fields = 5; + bool _descriptor_for_type = 6; + bool _initialization_error_string = 7; // TODO: re-enable - // optional bool _unknown_fields = 8; + // bool _unknown_fields = 8; // obsolete. kept for backwards compatibility of generated code - optional bool _cached_size = 9; + bool _cached_size = 9; } // Message with field names in camel case that conflict with accessors in the @@ -65,32 +68,32 @@ message ForbiddenWordsLeadingUnderscoreMessage { // src/google/protobuf/compiler/java/java_helpers.cc message ForbiddenWordsCamelMessage { // java.lang.Object - optional bool class = 1; + bool class = 1; // com.google.protobuf.MessageLiteOrBuilder - optional bool defaultInstanceForType = 2; + bool defaultInstanceForType = 2; // com.google.protobuf.MessageLite - optional bool serializedSize = 3; - optional bool parserForType = 4; + bool serializedSize = 3; + bool parserForType = 4; // com.google.protobuf.MessageOrBuilder: - optional bool initializationErrorString = 5; - optional bool descriptorForType = 6; - optional bool allFields = 7; + bool initializationErrorString = 5; + bool descriptorForType = 6; + bool allFields = 7; // TODO: re-enable - // optional bool unknownFields = 8; + // bool unknownFields = 8; // obsolete. kept for backwards compatibility of generated code - optional bool cachedSize = 9; + bool cachedSize = 9; } message Descriptor { option no_standard_descriptor_accessor = true; - optional string descriptor = 1; + string descriptor = 1; message NestedDescriptor { option no_standard_descriptor_accessor = true; - optional string descriptor = 1; + string descriptor = 1; } - optional NestedDescriptor nested_descriptor = 2; + NestedDescriptor nested_descriptor = 2; enum NestedEnum { UNKNOWN = 0; FOO = 1; @@ -102,7 +105,7 @@ message Parser { UNKNOWN = 0; PARSER = 1; } - optional ParserEnum parser = 1; + ParserEnum parser = 1; } message Deprecated { @@ -114,38 +117,38 @@ message Deprecated { BAR = 2 [deprecated = true]; } - optional int32 field1 = 1 [deprecated = true]; - optional TestEnum field2 = 2 [deprecated = true]; - optional ForbiddenWordsUnderscoreMessage field3 = 3 [deprecated = true]; + int32 field1 = 1 [deprecated = true]; + TestEnum field2 = 2 [deprecated = true]; + ForbiddenWordsUnderscoreMessage field3 = 3 [deprecated = true]; } message Override { - optional int32 override = 1; + int32 override = 1; } message Object { - optional int32 object = 1; - optional string string_object = 2; + int32 object = 1; + string string_object = 2; } message String { - optional string string = 1; + string string = 1; } message Integer { - optional int32 integer = 1; + int32 integer = 1; } message Long { - optional int32 long = 1; + int32 long = 1; } message Float { - optional float float = 1; + float float = 1; } message Double { - optional double double = 1; + double double = 1; } service TestConflictingMethodNames { @@ -168,11 +171,11 @@ message TestConflictingFieldNames { repeated bytes bytes_field = 4; repeated ForbiddenWordsUnderscoreMessage message_field = 5; - optional int32 int32_field_count = 11; - optional TestEnum enum_field_count = 12; - optional string string_field_count = 13; - optional bytes bytes_field_count = 14; - optional ForbiddenWordsUnderscoreMessage message_field_count = 15; + int32 int32_field_count = 11; + TestEnum enum_field_count = 12; + string string_field_count = 13; + bytes bytes_field_count = 14; + ForbiddenWordsUnderscoreMessage message_field_count = 15; repeated int32 Int32Field = 21; // NO_PROTO3 repeated TestEnum EnumField = 22; // NO_PROTO3 @@ -182,13 +185,14 @@ message TestConflictingFieldNames { // This field conflicts with "int32_field" as they both generate // the method getInt32FieldList(). - required int32 int32_field_list = 31; // NO_PROTO3 + int32 int32_field_list = 31 + [features.field_presence = LEGACY_REQUIRED]; // NO_PROTO3 // These field pairs have the same Java converted name - optional string field_name = 32; // NO_PROTO3 - optional string field__name = 33; // NO_PROTO3 - optional int32 _2conflict = 34; // NO_PROTO3 - optional int32 __2conflict = 35; + string field_name = 32; // NO_PROTO3 + string field__name = 33; // NO_PROTO3 + int32 _2conflict = 34; // NO_PROTO3 + int32 __2conflict = 35; extensions 1000 to max; // NO_PROTO3 @@ -196,9 +200,9 @@ message TestConflictingFieldNames { extend TestConflictingFieldNames { // NO_PROTO3 // We don't generate accessors for extensions so the following extension // fields don't conflict with the repeated field "int64_field". - optional int64 int64_field_count = 1001; // NO_PROTO3 - optional int64 int64_field_list = 1002; // NO_PROTO3 - } // NO_PROTO3 + int64 int64_field_count = 1001; // NO_PROTO3 + int64 int64_field_list = 1002; // NO_PROTO3 + } // NO_PROTO3 } message TestMapField { @@ -210,12 +214,12 @@ message TestMapField { } message TestLeadingNumberFields { - optional int32 _30day_impressions = 1; + int32 _30day_impressions = 1; repeated string _60day_impressions = 2; - optional string __2_underscores = 3; + string __2_underscores = 3; repeated string __2repeated_underscores = 4; - optional int32 _32 = 32; + int32 _32 = 32; repeated int64 _64 = 64; } diff --git a/java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto b/java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto index 06e1af657f..3af9831d29 100644 --- a/java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto +++ b/java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto @@ -8,21 +8,23 @@ // Author: Jacob Butcher (jbaum@google.com) // // Test file option java_string_check_utf8. -syntax = "proto2"; +edition = "2023"; package proto2_test_check_utf8; +option features.utf8_validation = VERIFY; option java_outer_classname = "TestCheckUtf8"; -option java_string_check_utf8 = true; message StringWrapper { - required string req = 1; - optional string opt = 2; + string req = 1 [features.field_presence = LEGACY_REQUIRED]; + + string opt = 2; repeated string rep = 3; } message BytesWrapper { - required bytes req = 1; - optional bytes opt = 2; + bytes req = 1 [features.field_presence = LEGACY_REQUIRED]; + + bytes opt = 2; repeated bytes rep = 3; } diff --git a/java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto b/java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto index 8e27a9b914..e4d09b95fd 100644 --- a/java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto +++ b/java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto @@ -8,22 +8,24 @@ // Author: Jacob Butcher (jbaum@google.com) // // Test file option java_string_check_utf8. -syntax = "proto2"; +edition = "2023"; package proto2_test_check_utf8_size; +option features.utf8_validation = VERIFY; option java_outer_classname = "TestCheckUtf8Size"; -option java_string_check_utf8 = true; option optimize_for = CODE_SIZE; message StringWrapperSize { - required string req = 1; - optional string opt = 2; + string req = 1 [features.field_presence = LEGACY_REQUIRED]; + + string opt = 2; repeated string rep = 3; } message BytesWrapperSize { - required bytes req = 1; - optional bytes opt = 2; + bytes req = 1 [features.field_presence = LEGACY_REQUIRED]; + + bytes opt = 2; repeated bytes rep = 3; } diff --git a/java/core/src/test/proto/com/google/protobuf/wrappers_test.proto b/java/core/src/test/proto/com/google/protobuf/wrappers_test.proto index dd2cee4dae..4ecf2dfe0d 100644 --- a/java/core/src/test/proto/com/google/protobuf/wrappers_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/wrappers_test.proto @@ -5,12 +5,13 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto3"; +edition = "2023"; package wrappers_test; import "google/protobuf/wrappers.proto"; +option features.field_presence = IMPLICIT; option java_package = "com.google.protobuf.wrapperstest"; option java_outer_classname = "WrappersTestProto"; diff --git a/java/kotlin-lite/BUILD.bazel b/java/kotlin-lite/BUILD.bazel index ca0686f089..873d0704cc 100644 --- a/java/kotlin-lite/BUILD.bazel +++ b/java/kotlin-lite/BUILD.bazel @@ -22,6 +22,7 @@ internal_gen_kt_protos( deps = [ "//:any_proto", "//:api_proto", + "//:descriptor_proto", "//:duration_proto", "//:empty_proto", "//:field_mask_proto", @@ -30,6 +31,7 @@ internal_gen_kt_protos( "//:timestamp_proto", "//:type_proto", "//:wrappers_proto", + "//java/core:java_features_proto", ], ) @@ -53,7 +55,11 @@ kt_jvm_export( ], maven_coordinates = "com.google.protobuf:protobuf-kotlin-lite:%s" % PROTOBUF_JAVA_VERSION, pom_template = "//java/kotlin-lite:pom_template.xml", - resources = ["//:well_known_type_protos"], + resources = [ + "//:well_known_type_protos", + "//java/core:java_features_proto", + "//src/google/protobuf:descriptor_proto_srcs", + ], tags = ["manual"], runtime_deps = [ ":lite_extensions", diff --git a/java/kotlin-lite/generate-sources-build.xml b/java/kotlin-lite/generate-sources-build.xml index ab9cfea4e3..b8728e2df8 100644 --- a/java/kotlin-lite/generate-sources-build.xml +++ b/java/kotlin-lite/generate-sources-build.xml @@ -4,8 +4,11 @@ + + + diff --git a/java/kotlin/BUILD.bazel b/java/kotlin/BUILD.bazel index 1b27a77dcd..804f9bd690 100644 --- a/java/kotlin/BUILD.bazel +++ b/java/kotlin/BUILD.bazel @@ -60,6 +60,7 @@ kt_jvm_export( pom_template = "//java/kotlin:pom_template.xml", resources = [ "//:well_known_type_protos", + "//java/core:java_features_proto", "//src/google/protobuf:descriptor_proto_srcs", ], tags = ["manual"], @@ -319,6 +320,7 @@ internal_gen_kt_protos( "//:timestamp_proto", "//:type_proto", "//:wrappers_proto", + "//java/core:java_features_proto", ], ) diff --git a/java/kotlin/generate-sources-build.xml b/java/kotlin/generate-sources-build.xml index 6963f3717f..9a0ec1dcc0 100644 --- a/java/kotlin/generate-sources-build.xml +++ b/java/kotlin/generate-sources-build.xml @@ -4,6 +4,8 @@ + + diff --git a/java/lite/BUILD.bazel b/java/lite/BUILD.bazel index 8311e9aa52..dba34cddd4 100644 --- a/java/lite/BUILD.bazel +++ b/java/lite/BUILD.bazel @@ -24,6 +24,7 @@ proto_lang_toolchain( name = "toolchain", # keep this in sync w/ LITE_WELL_KNOWN_PROTO_MAP in //:BUILD blacklisted_protos = [ + "//java/core:java_features_proto", "//:any_proto", "//:api_proto", "//:duration_proto", @@ -60,6 +61,7 @@ build_test( conformance_test( name = "conformance_test", failure_list = "//conformance:failure_list_java_lite.txt", + maximum_edition = "2023", testee = "//conformance:conformance_java_lite", text_format_failure_list = "//conformance:text_format_failure_list_java_lite.txt", ) diff --git a/java/lite/generate-sources-build.xml b/java/lite/generate-sources-build.xml index 74d96a2f10..b35bd63989 100644 --- a/java/lite/generate-sources-build.xml +++ b/java/lite/generate-sources-build.xml @@ -4,8 +4,11 @@ + + + diff --git a/java/lite/pom.xml b/java/lite/pom.xml index 85e6a88a6f..3121dd8c1a 100644 --- a/java/lite/pom.xml +++ b/java/lite/pom.xml @@ -47,6 +47,7 @@ google/protobuf/any.proto google/protobuf/api.proto + google/protobuf/descriptor.proto google/protobuf/duration.proto google/protobuf/empty.proto google/protobuf/field_mask.proto @@ -57,6 +58,12 @@ google/protobuf/wrappers.proto + + ${protobuf.java_source.dir} + + main/java/com/google/protobuf/java_features.proto + + @@ -214,6 +221,7 @@ GeneratedMessageTest.java LazyFieldTest.java LazyStringEndToEndTest.java + LazilyParsedMessageSetTest.java MapForProto2Test.java MapTest.java MessageTest.java diff --git a/java/osgi/osgi.bzl b/java/osgi/osgi.bzl index 68600b5d7b..8d88ba7fa6 100644 --- a/java/osgi/osgi.bzl +++ b/java/osgi/osgi.bzl @@ -174,7 +174,7 @@ def _osgi_jar_impl(ctx): source_jars = source_jars.to_list() if len(source_jars) > 1: fail("osgi_jar rule doesn't know how to deal with more than one source jar.") - source_jar = target_java_output.source_jars[0] + source_jar = source_jars[0] output_jar = ctx.outputs.output_jar diff --git a/java/util/pom.xml b/java/util/pom.xml index 0ce7107663..818081d24b 100644 --- a/java/util/pom.xml +++ b/java/util/pom.xml @@ -88,6 +88,7 @@ + diff --git a/lua/lua_proto_library.bzl b/lua/lua_proto_library.bzl index 0f80f81cef..6eac2e54e2 100644 --- a/lua/lua_proto_library.bzl +++ b/lua/lua_proto_library.bzl @@ -124,7 +124,6 @@ _lua_proto_library_aspect = aspect( ) lua_proto_library = rule( - output_to_genfiles = True, implementation = _lua_proto_rule_impl, attrs = { "deps": attr.label_list( diff --git a/php/ext/google/protobuf/php-upb.c b/php/ext/google/protobuf/php-upb.c index b1fec7df10..51d44d8694 100644 --- a/php/ext/google/protobuf/php-upb.c +++ b/php/ext/google/protobuf/php-upb.c @@ -305,10 +305,10 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); /* Disable proto2 arena behavior (TEMPORARY) **********************************/ -#ifdef UPB_DISABLE_PROTO2_ENUM_CHECKING -#define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 1 +#ifdef UPB_DISABLE_CLOSED_ENUM_CHECKING +#define UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN 1 #else -#define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 0 +#define UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN 0 #endif #if defined(__cplusplus) @@ -1737,7 +1737,7 @@ const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout = { * regenerated. */ -static const char descriptor[11630] = {'\n', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'e', 's', 'c', 'r', 'i', 'p', +static const char descriptor[11638] = {'\n', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '\"', 'M', '\n', '\021', 'F', 'i', 'l', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'S', 'e', 't', '\022', '8', '\n', '\004', 'f', 'i', 'l', 'e', '\030', '\001', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', @@ -2093,7 +2093,7 @@ static const char descriptor[11630] = {'\n', ' ', 'g', 'o', 'o', 'g', 'l', 'e', 't', 'e', 'V', 'a', 'l', 'u', 'e', '\032', 'J', '\n', '\010', 'N', 'a', 'm', 'e', 'P', 'a', 'r', 't', '\022', '\033', '\n', '\t', 'n', 'a', 'm', 'e', '_', 'p', 'a', 'r', 't', '\030', '\001', ' ', '\002', '(', '\t', 'R', '\010', 'n', 'a', 'm', 'e', 'P', 'a', 'r', 't', '\022', '!', '\n', '\014', 'i', 's', '_', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\030', '\002', ' ', '\002', '(', '\010', 'R', '\013', 'i', 's', 'E', -'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\"', '\214', '\n', '\n', '\n', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', '\022', '\213', +'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\"', '\224', '\n', '\n', '\n', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', '\022', '\213', '\001', '\n', '\016', 'f', 'i', 'e', 'l', 'd', '_', 'p', 'r', 'e', 's', 'e', 'n', 'c', 'e', '\030', '\001', ' ', '\001', '(', '\016', '2', ')', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', '.', 'F', 'i', 'e', 'l', 'd', 'P', 'r', 'e', 's', 'e', 'n', 'c', 'e', 'B', '9', '\210', '\001', '\001', '\230', '\001', '\004', '\230', @@ -2144,65 +2144,65 @@ static const char descriptor[11630] = {'\n', ' ', 'g', 'o', 'o', 'g', 'l', 'e', 'S', 'O', 'N', '_', 'F', 'O', 'R', 'M', 'A', 'T', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\t', '\n', '\005', 'A', 'L', 'L', 'O', 'W', '\020', '\001', '\022', '\026', '\n', '\022', 'L', 'E', 'G', 'A', 'C', 'Y', '_', 'B', 'E', 'S', 'T', '_', 'E', 'F', 'F', 'O', 'R', 'T', '\020', '\002', '*', '\006', '\010', '\350', '\007', '\020', '\351', '\007', '*', '\006', '\010', '\351', '\007', '\020', '\352', '\007', '*', '\006', '\010', '\352', -'\007', '\020', '\353', '\007', '*', '\006', '\010', '\213', 'N', '\020', '\220', 'N', '*', '\006', '\010', '\220', 'N', '\020', '\221', 'N', 'J', '\006', '\010', '\347', '\007', -'\020', '\350', '\007', '\"', '\376', '\002', '\n', '\022', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'D', 'e', 'f', 'a', 'u', 'l', 't', -'s', '\022', 'X', '\n', '\010', 'd', 'e', 'f', 'a', 'u', 'l', 't', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '<', '.', 'g', 'o', 'o', -'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'D', 'e', -'f', 'a', 'u', 'l', 't', 's', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'D', -'e', 'f', 'a', 'u', 'l', 't', 'R', '\010', 'd', 'e', 'f', 'a', 'u', 'l', 't', 's', '\022', 'A', '\n', '\017', 'm', 'i', 'n', 'i', 'm', -'u', 'm', '_', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\004', ' ', '\001', '(', '\016', '2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', -'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'R', '\016', 'm', 'i', 'n', 'i', 'm', 'u', -'m', 'E', 'd', 'i', 't', 'i', 'o', 'n', '\022', 'A', '\n', '\017', 'm', 'a', 'x', 'i', 'm', 'u', 'm', '_', 'e', 'd', 'i', 't', 'i', -'o', 'n', '\030', '\005', ' ', '\001', '(', '\016', '2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', -'f', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'R', '\016', 'm', 'a', 'x', 'i', 'm', 'u', 'm', 'E', 'd', 'i', 't', 'i', 'o', 'n', -'\032', '\207', '\001', '\n', '\030', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'D', 'e', 'f', -'a', 'u', 'l', 't', '\022', '2', '\n', '\007', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', '\016', '2', '\030', '.', 'g', -'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'R', '\007', 'e', -'d', 'i', 't', 'i', 'o', 'n', '\022', '7', '\n', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', -'\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', -'S', 'e', 't', 'R', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\"', '\247', '\002', '\n', '\016', 'S', 'o', 'u', 'r', 'c', 'e', 'C', -'o', 'd', 'e', 'I', 'n', 'f', 'o', '\022', 'D', '\n', '\010', 'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\030', '\001', ' ', '\003', '(', '\013', -'2', '(', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'o', 'u', 'r', 'c', 'e', -'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '.', 'L', 'o', 'c', 'a', 't', 'i', 'o', 'n', 'R', '\010', 'l', 'o', 'c', 'a', 't', 'i', -'o', 'n', '\032', '\316', '\001', '\n', '\010', 'L', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\022', '\026', '\n', '\004', 'p', 'a', 't', 'h', '\030', '\001', -' ', '\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', '\004', 'p', 'a', 't', 'h', '\022', '\026', '\n', '\004', 's', 'p', 'a', 'n', '\030', '\002', ' ', -'\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', '\004', 's', 'p', 'a', 'n', '\022', ')', '\n', '\020', 'l', 'e', 'a', 'd', 'i', 'n', 'g', '_', -'c', 'o', 'm', 'm', 'e', 'n', 't', 's', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\017', 'l', 'e', 'a', 'd', 'i', 'n', 'g', 'C', 'o', -'m', 'm', 'e', 'n', 't', 's', '\022', '+', '\n', '\021', 't', 'r', 'a', 'i', 'l', 'i', 'n', 'g', '_', 'c', 'o', 'm', 'm', 'e', 'n', -'t', 's', '\030', '\004', ' ', '\001', '(', '\t', 'R', '\020', 't', 'r', 'a', 'i', 'l', 'i', 'n', 'g', 'C', 'o', 'm', 'm', 'e', 'n', 't', -'s', '\022', ':', '\n', '\031', 'l', 'e', 'a', 'd', 'i', 'n', 'g', '_', 'd', 'e', 't', 'a', 'c', 'h', 'e', 'd', '_', 'c', 'o', 'm', -'m', 'e', 'n', 't', 's', '\030', '\006', ' ', '\003', '(', '\t', 'R', '\027', 'l', 'e', 'a', 'd', 'i', 'n', 'g', 'D', 'e', 't', 'a', 'c', -'h', 'e', 'd', 'C', 'o', 'm', 'm', 'e', 'n', 't', 's', '\"', '\320', '\002', '\n', '\021', 'G', 'e', 'n', 'e', 'r', 'a', 't', 'e', 'd', -'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '\022', 'M', '\n', '\n', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '\030', '\001', ' ', -'\003', '(', '\013', '2', '-', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'G', 'e', 'n', -'e', 'r', 'a', 't', 'e', 'd', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '.', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', -'R', '\n', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '\032', '\353', '\001', '\n', '\n', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', -'o', 'n', '\022', '\026', '\n', '\004', 'p', 'a', 't', 'h', '\030', '\001', ' ', '\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', '\004', 'p', 'a', 't', -'h', '\022', '\037', '\n', '\013', 's', 'o', 'u', 'r', 'c', 'e', '_', 'f', 'i', 'l', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\n', 's', -'o', 'u', 'r', 'c', 'e', 'F', 'i', 'l', 'e', '\022', '\024', '\n', '\005', 'b', 'e', 'g', 'i', 'n', '\030', '\003', ' ', '\001', '(', '\005', 'R', -'\005', 'b', 'e', 'g', 'i', 'n', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\004', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', '\022', -'R', '\n', '\010', 's', 'e', 'm', 'a', 'n', 't', 'i', 'c', '\030', '\005', ' ', '\001', '(', '\016', '2', '6', '.', 'g', 'o', 'o', 'g', 'l', -'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'G', 'e', 'n', 'e', 'r', 'a', 't', 'e', 'd', 'C', 'o', 'd', 'e', 'I', -'n', 'f', 'o', '.', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '.', 'S', 'e', 'm', 'a', 'n', 't', 'i', 'c', 'R', '\010', -'s', 'e', 'm', 'a', 'n', 't', 'i', 'c', '\"', '(', '\n', '\010', 'S', 'e', 'm', 'a', 'n', 't', 'i', 'c', '\022', '\010', '\n', '\004', 'N', -'O', 'N', 'E', '\020', '\000', '\022', '\007', '\n', '\003', 'S', 'E', 'T', '\020', '\001', '\022', '\t', '\n', '\005', 'A', 'L', 'I', 'A', 'S', '\020', '\002', -'*', '\222', '\002', '\n', '\007', 'E', 'd', 'i', 't', 'i', 'o', 'n', '\022', '\023', '\n', '\017', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', 'U', -'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\023', '\n', '\016', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', 'P', 'R', 'O', 'T', 'O', -'2', '\020', '\346', '\007', '\022', '\023', '\n', '\016', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', 'P', 'R', 'O', 'T', 'O', '3', '\020', '\347', '\007', -'\022', '\021', '\n', '\014', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', '2', '0', '2', '3', '\020', '\350', '\007', '\022', '\021', '\n', '\014', 'E', 'D', -'I', 'T', 'I', 'O', 'N', '_', '2', '0', '2', '4', '\020', '\351', '\007', '\022', '\027', '\n', '\023', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', -'1', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', 'L', 'Y', '\020', '\001', '\022', '\027', '\n', '\023', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', -'2', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', 'L', 'Y', '\020', '\002', '\022', '\035', '\n', '\027', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', -'9', '9', '9', '9', '7', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', 'L', 'Y', '\020', '\235', '\215', '\006', '\022', '\035', '\n', '\027', 'E', 'D', -'I', 'T', 'I', 'O', 'N', '_', '9', '9', '9', '9', '8', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', 'L', 'Y', '\020', '\236', '\215', '\006', -'\022', '\035', '\n', '\027', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', '9', '9', '9', '9', '9', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', -'L', 'Y', '\020', '\237', '\215', '\006', '\022', '\023', '\n', '\013', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', 'M', 'A', 'X', '\020', '\377', '\377', '\377', -'\377', '\007', 'B', '~', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', -'B', '\020', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 's', 'H', '\001', 'Z', '-', 'g', 'o', 'o', -'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', -'y', 'p', 'e', 's', '/', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', -'B', '\252', '\002', '\032', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'R', 'e', 'f', 'l', 'e', -'c', 't', 'i', 'o', 'n', +'\007', '\020', '\353', '\007', '*', '\006', '\010', '\206', 'N', '\020', '\207', 'N', '*', '\006', '\010', '\213', 'N', '\020', '\220', 'N', '*', '\006', '\010', '\220', 'N', +'\020', '\221', 'N', 'J', '\006', '\010', '\347', '\007', '\020', '\350', '\007', '\"', '\376', '\002', '\n', '\022', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', +'t', 'D', 'e', 'f', 'a', 'u', 'l', 't', 's', '\022', 'X', '\n', '\010', 'd', 'e', 'f', 'a', 'u', 'l', 't', 's', '\030', '\001', ' ', '\003', +'(', '\013', '2', '<', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', +'u', 'r', 'e', 'S', 'e', 't', 'D', 'e', 'f', 'a', 'u', 'l', 't', 's', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', +'E', 'd', 'i', 't', 'i', 'o', 'n', 'D', 'e', 'f', 'a', 'u', 'l', 't', 'R', '\010', 'd', 'e', 'f', 'a', 'u', 'l', 't', 's', '\022', +'A', '\n', '\017', 'm', 'i', 'n', 'i', 'm', 'u', 'm', '_', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\004', ' ', '\001', '(', '\016', '2', +'\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', +'R', '\016', 'm', 'i', 'n', 'i', 'm', 'u', 'm', 'E', 'd', 'i', 't', 'i', 'o', 'n', '\022', 'A', '\n', '\017', 'm', 'a', 'x', 'i', 'm', +'u', 'm', '_', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\005', ' ', '\001', '(', '\016', '2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', +'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'R', '\016', 'm', 'a', 'x', 'i', 'm', 'u', +'m', 'E', 'd', 'i', 't', 'i', 'o', 'n', '\032', '\207', '\001', '\n', '\030', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'E', 'd', +'i', 't', 'i', 'o', 'n', 'D', 'e', 'f', 'a', 'u', 'l', 't', '\022', '2', '\n', '\007', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\003', +' ', '\001', '(', '\016', '2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'd', +'i', 't', 'i', 'o', 'n', 'R', '\007', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\022', '7', '\n', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', +'s', '\030', '\002', ' ', '\001', '(', '\013', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', +'.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'R', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\"', '\247', '\002', '\n', +'\016', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '\022', 'D', '\n', '\010', 'l', 'o', 'c', 'a', 't', 'i', +'o', 'n', '\030', '\001', ' ', '\003', '(', '\013', '2', '(', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '.', 'L', 'o', 'c', 'a', 't', 'i', 'o', 'n', +'R', '\010', 'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\032', '\316', '\001', '\n', '\010', 'L', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\022', '\026', +'\n', '\004', 'p', 'a', 't', 'h', '\030', '\001', ' ', '\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', '\004', 'p', 'a', 't', 'h', '\022', '\026', '\n', +'\004', 's', 'p', 'a', 'n', '\030', '\002', ' ', '\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', '\004', 's', 'p', 'a', 'n', '\022', ')', '\n', '\020', +'l', 'e', 'a', 'd', 'i', 'n', 'g', '_', 'c', 'o', 'm', 'm', 'e', 'n', 't', 's', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\017', 'l', +'e', 'a', 'd', 'i', 'n', 'g', 'C', 'o', 'm', 'm', 'e', 'n', 't', 's', '\022', '+', '\n', '\021', 't', 'r', 'a', 'i', 'l', 'i', 'n', +'g', '_', 'c', 'o', 'm', 'm', 'e', 'n', 't', 's', '\030', '\004', ' ', '\001', '(', '\t', 'R', '\020', 't', 'r', 'a', 'i', 'l', 'i', 'n', +'g', 'C', 'o', 'm', 'm', 'e', 'n', 't', 's', '\022', ':', '\n', '\031', 'l', 'e', 'a', 'd', 'i', 'n', 'g', '_', 'd', 'e', 't', 'a', +'c', 'h', 'e', 'd', '_', 'c', 'o', 'm', 'm', 'e', 'n', 't', 's', '\030', '\006', ' ', '\003', '(', '\t', 'R', '\027', 'l', 'e', 'a', 'd', +'i', 'n', 'g', 'D', 'e', 't', 'a', 'c', 'h', 'e', 'd', 'C', 'o', 'm', 'm', 'e', 'n', 't', 's', '\"', '\320', '\002', '\n', '\021', 'G', +'e', 'n', 'e', 'r', 'a', 't', 'e', 'd', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '\022', 'M', '\n', '\n', 'a', 'n', 'n', 'o', 't', +'a', 't', 'i', 'o', 'n', '\030', '\001', ' ', '\003', '(', '\013', '2', '-', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', +'o', 'b', 'u', 'f', '.', 'G', 'e', 'n', 'e', 'r', 'a', 't', 'e', 'd', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '.', 'A', 'n', +'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 'R', '\n', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '\032', '\353', '\001', '\n', '\n', +'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '\022', '\026', '\n', '\004', 'p', 'a', 't', 'h', '\030', '\001', ' ', '\003', '(', '\005', 'B', +'\002', '\020', '\001', 'R', '\004', 'p', 'a', 't', 'h', '\022', '\037', '\n', '\013', 's', 'o', 'u', 'r', 'c', 'e', '_', 'f', 'i', 'l', 'e', '\030', +'\002', ' ', '\001', '(', '\t', 'R', '\n', 's', 'o', 'u', 'r', 'c', 'e', 'F', 'i', 'l', 'e', '\022', '\024', '\n', '\005', 'b', 'e', 'g', 'i', +'n', '\030', '\003', ' ', '\001', '(', '\005', 'R', '\005', 'b', 'e', 'g', 'i', 'n', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\004', ' ', '\001', +'(', '\005', 'R', '\003', 'e', 'n', 'd', '\022', 'R', '\n', '\010', 's', 'e', 'm', 'a', 'n', 't', 'i', 'c', '\030', '\005', ' ', '\001', '(', '\016', +'2', '6', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'G', 'e', 'n', 'e', 'r', 'a', +'t', 'e', 'd', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '.', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '.', 'S', 'e', +'m', 'a', 'n', 't', 'i', 'c', 'R', '\010', 's', 'e', 'm', 'a', 'n', 't', 'i', 'c', '\"', '(', '\n', '\010', 'S', 'e', 'm', 'a', 'n', +'t', 'i', 'c', '\022', '\010', '\n', '\004', 'N', 'O', 'N', 'E', '\020', '\000', '\022', '\007', '\n', '\003', 'S', 'E', 'T', '\020', '\001', '\022', '\t', '\n', +'\005', 'A', 'L', 'I', 'A', 'S', '\020', '\002', '*', '\222', '\002', '\n', '\007', 'E', 'd', 'i', 't', 'i', 'o', 'n', '\022', '\023', '\n', '\017', 'E', +'D', 'I', 'T', 'I', 'O', 'N', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\023', '\n', '\016', 'E', 'D', 'I', 'T', 'I', +'O', 'N', '_', 'P', 'R', 'O', 'T', 'O', '2', '\020', '\346', '\007', '\022', '\023', '\n', '\016', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', 'P', +'R', 'O', 'T', 'O', '3', '\020', '\347', '\007', '\022', '\021', '\n', '\014', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', '2', '0', '2', '3', '\020', +'\350', '\007', '\022', '\021', '\n', '\014', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', '2', '0', '2', '4', '\020', '\351', '\007', '\022', '\027', '\n', '\023', +'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', '1', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', 'L', 'Y', '\020', '\001', '\022', '\027', '\n', '\023', +'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', '2', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', 'L', 'Y', '\020', '\002', '\022', '\035', '\n', '\027', +'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', '9', '9', '9', '9', '7', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', 'L', 'Y', '\020', '\235', +'\215', '\006', '\022', '\035', '\n', '\027', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', '9', '9', '9', '9', '8', '_', 'T', 'E', 'S', 'T', '_', +'O', 'N', 'L', 'Y', '\020', '\236', '\215', '\006', '\022', '\035', '\n', '\027', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', '9', '9', '9', '9', '9', +'_', 'T', 'E', 'S', 'T', '_', 'O', 'N', 'L', 'Y', '\020', '\237', '\215', '\006', '\022', '\023', '\n', '\013', 'E', 'D', 'I', 'T', 'I', 'O', 'N', +'_', 'M', 'A', 'X', '\020', '\377', '\377', '\377', '\377', '\007', 'B', '~', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\020', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', +'s', 'H', '\001', 'Z', '-', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', +'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'p', 'b', +'\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\032', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', +'u', 'f', '.', 'R', 'e', 'f', 'l', 'e', 'c', 't', 'i', 'o', 'n', }; static _upb_DefPool_Init *deps[1] = { @@ -2213,7 +2213,7 @@ _upb_DefPool_Init google_protobuf_descriptor_proto_upbdefinit = { deps, &google_protobuf_descriptor_proto_upb_file_layout, "google/protobuf/descriptor.proto", - UPB_STRINGVIEW_INIT(descriptor, 11630) + UPB_STRINGVIEW_INIT(descriptor, 11638) }; @@ -4530,6 +4530,10 @@ static void* upb_global_allocfunc(upb_alloc* alloc, void* ptr, size_t oldsize, upb_alloc upb_alloc_global = {&upb_global_allocfunc}; +#ifdef UPB_TRACING_ENABLED +#include +#endif + #include #include @@ -4636,6 +4640,38 @@ static bool _upb_ArenaInternal_HasInitialBlock(upb_ArenaInternal* ai) { return ai->block_alloc & 0x1; } +#ifdef UPB_TRACING_ENABLED +static void (*_init_arena_trace_handler)(const upb_Arena*, size_t size) = NULL; +static void (*_fuse_arena_trace_handler)(const upb_Arena*, + const upb_Arena*) = NULL; +static void (*_free_arena_trace_handler)(const upb_Arena*) = NULL; + +void upb_Arena_SetTraceHandler( + void (*initArenaTraceHandler)(const upb_Arena*, size_t size), + void (*fuseArenaTraceHandler)(const upb_Arena*, const upb_Arena*), + void (*freeArenaTraceHandler)(const upb_Arena*)) { + _init_arena_trace_handler = initArenaTraceHandler; + _fuse_arena_trace_handler = fuseArenaTraceHandler; + _free_arena_trace_handler = freeArenaTraceHandler; +} + +void upb_Arena_LogInit(const upb_Arena* arena, size_t size) { + if (_init_arena_trace_handler) { + _init_arena_trace_handler(arena, size); + } +} +void upb_Arena_LogFuse(const upb_Arena* arena1, const upb_Arena* arena2) { + if (_fuse_arena_trace_handler) { + _fuse_arena_trace_handler(arena1, arena2); + } +} +void upb_Arena_LogFree(const upb_Arena* arena) { + if (_free_arena_trace_handler) { + _free_arena_trace_handler(arena); + } +} +#endif // UPB_TRACING_ENABLED + static upb_ArenaRoot _upb_Arena_FindRoot(upb_Arena* a) { upb_ArenaInternal* ai = upb_Arena_Internal(a); uintptr_t poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); @@ -4799,7 +4835,13 @@ upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) { n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_ArenaState)); if (UPB_UNLIKELY(n < sizeof(upb_ArenaState))) { +#ifdef UPB_TRACING_ENABLED + upb_Arena* ret = _upb_Arena_InitSlow(alloc); + upb_Arena_LogInit(ret, n); + return ret; +#else return _upb_Arena_InitSlow(alloc); +#endif } a = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), upb_ArenaState); @@ -4812,13 +4854,14 @@ upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) { a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 1); a->head.UPB_PRIVATE(ptr) = mem; a->head.UPB_PRIVATE(end) = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), char); - +#ifdef UPB_TRACING_ENABLED + upb_Arena_LogInit(&a->head, n); +#endif return &a->head; } static void _upb_Arena_DoFree(upb_ArenaInternal* ai) { UPB_ASSERT(_upb_Arena_RefCountFromTagged(ai->parent_or_count) == 1); - while (ai != NULL) { // Load first since arena itself is likely from one of its blocks. upb_ArenaInternal* next_arena = @@ -4849,6 +4892,9 @@ retry: // expensive then direct loads. As an optimization, we only do RMW ops // when we need to update things for other threads to see. if (poc == _upb_Arena_TaggedFromRefcount(1)) { +#ifdef UPB_TRACING_ENABLED + upb_Arena_LogFree(a); +#endif _upb_Arena_DoFree(ai); return; } @@ -4968,6 +5014,10 @@ static bool _upb_Arena_FixupRefs(upb_ArenaInternal* new_root, bool upb_Arena_Fuse(upb_Arena* a1, upb_Arena* a2) { if (a1 == a2) return true; // trivial fuse +#ifdef UPB_TRACING_ENABLED + upb_Arena_LogFuse(a1, a2); +#endif + upb_ArenaInternal* ai1 = upb_Arena_Internal(a1); upb_ArenaInternal* ai2 = upb_Arena_Internal(a2); @@ -11890,13 +11940,13 @@ bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need, static void (*_new_message_trace_handler)(const upb_MiniTable*, const upb_Arena*); -void upb_Message_SetNewMessageTraceHandler( +void UPB_PRIVATE(upb_Message_SetNewMessageTraceHandler)( void (*new_message_trace_handler)(const upb_MiniTable*, const upb_Arena*)) { _new_message_trace_handler = new_message_trace_handler; } -void upb_Message_LogNewMessage(const upb_MiniTable* mini_table, - const upb_Arena* arena) { +void UPB_PRIVATE(upb_Message_LogNewMessage)(const upb_MiniTable* mini_table, + const upb_Arena* arena) { if (_new_message_trace_handler) { _new_message_trace_handler(mini_table, arena); } @@ -12932,7 +12982,11 @@ const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i) { } bool upb_EnumDef_IsClosed(const upb_EnumDef* e) { - if (UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3) return false; + if (UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN) return false; + return upb_EnumDef_IsSpecifiedAsClosed(e); +} + +bool upb_EnumDef_IsSpecifiedAsClosed(const upb_EnumDef* e) { return UPB_DESC(FeatureSet_enum_type)(e->resolved_features) == UPB_DESC(FeatureSet_CLOSED); } @@ -13238,15 +13292,10 @@ static void create_enumvaldef(upb_DefBuilder* ctx, const char* prefix, static void _upb_EnumValueDef_CheckZeroValue(upb_DefBuilder* ctx, const upb_EnumDef* e, const upb_EnumValueDef* v, int n) { - if (upb_EnumDef_IsClosed(e) || n == 0 || v[0].number == 0) return; - - // When the special UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 is enabled, we have to - // exempt proto2 enums from this check, even when we are treating them as + // When the special UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN is enabled, we have to + // exempt closed enums from this check, even when we are treating them as // open. - if (UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 && - upb_FileDef_Syntax(upb_EnumDef_File(e)) == kUpb_Syntax_Proto2) { - return; - } + if (upb_EnumDef_IsSpecifiedAsClosed(e) || n == 0 || v[0].number == 0) return; _upb_DefBuilder_Errf(ctx, "for open enums, the first value must be zero (%s)", upb_EnumDef_FullName(e)); @@ -13440,6 +13489,10 @@ upb_FieldType upb_FieldDef_Type(const upb_FieldDef* f) { uint32_t upb_FieldDef_Index(const upb_FieldDef* f) { return f->index_; } +uint32_t upb_FieldDef_LayoutIndex(const upb_FieldDef* f) { + return f->layout_index; +} + upb_Label upb_FieldDef_Label(const upb_FieldDef* f) { // TODO: remove once we can deprecate kUpb_Label_Required. if (UPB_DESC(FeatureSet_field_presence)(f->resolved_features) == @@ -16603,7 +16656,7 @@ upb_ServiceDef* _upb_ServiceDefs_New(upb_DefBuilder* ctx, int n, #undef UPB_ASAN #undef UPB_ASAN_GUARD_SIZE #undef UPB_CLANG_ASAN -#undef UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 +#undef UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN #undef UPB_DEPRECATED #undef UPB_GNUC_MIN #undef UPB_DESCRIPTOR_UPB_H_FILENAME diff --git a/php/ext/google/protobuf/php-upb.h b/php/ext/google/protobuf/php-upb.h index fec53ae323..5c1080afa9 100644 --- a/php/ext/google/protobuf/php-upb.h +++ b/php/ext/google/protobuf/php-upb.h @@ -304,10 +304,10 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); /* Disable proto2 arena behavior (TEMPORARY) **********************************/ -#ifdef UPB_DISABLE_PROTO2_ENUM_CHECKING -#define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 1 +#ifdef UPB_DISABLE_CLOSED_ENUM_CHECKING +#define UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN 1 #else -#define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 0 +#define UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN 0 #endif #if defined(__cplusplus) @@ -806,6 +806,14 @@ UPB_API_INLINE void* upb_Arena_Realloc(upb_Arena* a, void* ptr, size_t oldsize, UPB_API_INLINE void upb_Arena_ShrinkLast(upb_Arena* a, void* ptr, size_t oldsize, size_t size); +#ifdef UPB_TRACING_ENABLED +void upb_Arena_SetTraceHandler(void (*initArenaTraceHandler)(const upb_Arena*, + size_t size), + void (*fuseArenaTraceHandler)(const upb_Arena*, + const upb_Arena*), + void (*freeArenaTraceHandler)(const upb_Arena*)); +#endif + #ifdef __cplusplus } /* extern "C" */ #endif @@ -2442,17 +2450,17 @@ typedef struct upb_Message_Internal { } upb_Message_Internal; #ifdef UPB_TRACING_ENABLED -void upb_Message_SetNewMessageTraceHandler( +void UPB_PRIVATE(upb_Message_SetNewMessageTraceHandler)( void (*newMessageTraceHandler)(const upb_MiniTable*, const upb_Arena*)); -void upb_Message_LogNewMessage(const upb_MiniTable* mini_table, - const upb_Arena* arena); +void UPB_PRIVATE(upb_Message_LogNewMessage)(const upb_MiniTable* mini_table, + const upb_Arena* arena); #endif // Inline version upb_Message_New(), for internal use. UPB_INLINE struct upb_Message* _upb_Message_New(const upb_MiniTable* m, upb_Arena* a) { #ifdef UPB_TRACING_ENABLED - upb_Message_LogNewMessage(m, a); + UPB_PRIVATE(upb_Message_LogNewMessage)(m, a); #endif const int size = m->UPB_PRIVATE(size); struct upb_Message* msg = (struct upb_Message*)upb_Arena_Malloc(a, size); @@ -2969,12 +2977,6 @@ UPB_API_INLINE bool upb_Map_Set(upb_Map* map, upb_MessageValue key, UPB_API bool upb_Map_Delete(upb_Map* map, upb_MessageValue key, upb_MessageValue* val); -// (DEPRECATED and going away soon. Do not use.) -UPB_INLINE bool upb_Map_Delete2(upb_Map* map, upb_MessageValue key, - upb_MessageValue* val) { - return upb_Map_Delete(map, key, val); -} - // Map iteration: // // size_t iter = kUpb_Map_Begin; @@ -3075,6 +3077,18 @@ UPB_API void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m); // Returns whether a message has been frozen. UPB_API_INLINE bool upb_Message_IsFrozen(const upb_Message* msg); +#ifdef UPB_TRACING_ENABLED +UPB_INLINE void upb_Message_SetNewMessageTraceHandler( + void (*newMessageTraceHandler)(const upb_MiniTable* mini_table, + const upb_Arena* arena)) { + UPB_PRIVATE(upb_Message_SetNewMessageTraceHandler)(newMessageTraceHandler); +} +UPB_INLINE void upb_Message_LogNewMessage(const upb_MiniTable* mini_table, + const upb_Arena* arena) { + UPB_PRIVATE(upb_Message_LogNewMessage)(mini_table, arena); +} +#endif + #ifdef __cplusplus } /* extern "C" */ #endif @@ -11064,8 +11078,8 @@ const upb_FieldDef* upb_DefPool_FindExtensionByNumber(const upb_DefPool* s, const upb_MessageDef* m, int32_t fieldnum); -const upb_ServiceDef* upb_DefPool_FindServiceByName(const upb_DefPool* s, - const char* name); +UPB_API const upb_ServiceDef* upb_DefPool_FindServiceByName( + const upb_DefPool* s, const char* name); const upb_ServiceDef* upb_DefPool_FindServiceByNameWithSize( const upb_DefPool* s, const char* name, size_t size); @@ -11116,6 +11130,7 @@ UPB_API const upb_EnumValueDef* upb_EnumDef_FindValueByNumber( UPB_API const char* upb_EnumDef_FullName(const upb_EnumDef* e); bool upb_EnumDef_HasOptions(const upb_EnumDef* e); bool upb_EnumDef_IsClosed(const upb_EnumDef* e); +bool upb_EnumDef_IsSpecifiedAsClosed(const upb_EnumDef* e); // Creates a mini descriptor string for an enum, returns true on success. bool upb_EnumDef_MiniDescriptorEncode(const upb_EnumDef* e, upb_Arena* a, @@ -11244,6 +11259,7 @@ bool upb_FieldDef_IsString(const upb_FieldDef* f); UPB_API bool upb_FieldDef_IsSubMessage(const upb_FieldDef* f); UPB_API const char* upb_FieldDef_JsonName(const upb_FieldDef* f); UPB_API upb_Label upb_FieldDef_Label(const upb_FieldDef* f); +uint32_t upb_FieldDef_LayoutIndex(const upb_FieldDef* f); UPB_API const upb_MessageDef* upb_FieldDef_MessageSubDef(const upb_FieldDef* f); bool _upb_FieldDef_ValidateUtf8(const upb_FieldDef* f); @@ -11481,18 +11497,19 @@ UPB_API upb_WellKnown upb_MessageDef_WellKnownType(const upb_MessageDef* m); extern "C" { #endif -bool upb_MethodDef_ClientStreaming(const upb_MethodDef* m); +UPB_API bool upb_MethodDef_ClientStreaming(const upb_MethodDef* m); const char* upb_MethodDef_FullName(const upb_MethodDef* m); bool upb_MethodDef_HasOptions(const upb_MethodDef* m); int upb_MethodDef_Index(const upb_MethodDef* m); -const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m); -const char* upb_MethodDef_Name(const upb_MethodDef* m); -const UPB_DESC(MethodOptions) * upb_MethodDef_Options(const upb_MethodDef* m); +UPB_API const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m); +UPB_API const char* upb_MethodDef_Name(const upb_MethodDef* m); +UPB_API const UPB_DESC(MethodOptions) * + upb_MethodDef_Options(const upb_MethodDef* m); const UPB_DESC(FeatureSet) * upb_MethodDef_ResolvedFeatures(const upb_MethodDef* m); -const upb_MessageDef* upb_MethodDef_OutputType(const upb_MethodDef* m); -bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m); -const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m); +UPB_API const upb_MessageDef* upb_MethodDef_OutputType(const upb_MethodDef* m); +UPB_API bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m); +UPB_API const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m); #ifdef __cplusplus } /* extern "C" */ @@ -11553,16 +11570,17 @@ const UPB_DESC(FeatureSet*) extern "C" { #endif -const upb_FileDef* upb_ServiceDef_File(const upb_ServiceDef* s); +UPB_API const upb_FileDef* upb_ServiceDef_File(const upb_ServiceDef* s); const upb_MethodDef* upb_ServiceDef_FindMethodByName(const upb_ServiceDef* s, const char* name); -const char* upb_ServiceDef_FullName(const upb_ServiceDef* s); +UPB_API const char* upb_ServiceDef_FullName(const upb_ServiceDef* s); bool upb_ServiceDef_HasOptions(const upb_ServiceDef* s); int upb_ServiceDef_Index(const upb_ServiceDef* s); -const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, int i); -int upb_ServiceDef_MethodCount(const upb_ServiceDef* s); +UPB_API const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, + int i); +UPB_API int upb_ServiceDef_MethodCount(const upb_ServiceDef* s); const char* upb_ServiceDef_Name(const upb_ServiceDef* s); -const UPB_DESC(ServiceOptions) * +UPB_API const UPB_DESC(ServiceOptions) * upb_ServiceDef_Options(const upb_ServiceDef* s); const UPB_DESC(FeatureSet) * upb_ServiceDef_ResolvedFeatures(const upb_ServiceDef* s); @@ -14254,7 +14272,7 @@ upb_MethodDef* _upb_MethodDefs_New(upb_DefBuilder* ctx, int n, #undef UPB_ASAN #undef UPB_ASAN_GUARD_SIZE #undef UPB_CLANG_ASAN -#undef UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 +#undef UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN #undef UPB_DEPRECATED #undef UPB_GNUC_MIN #undef UPB_DESCRIPTOR_UPB_H_FILENAME diff --git a/pkg/BUILD.bazel b/pkg/BUILD.bazel index 85df654a03..b87b4e9745 100644 --- a/pkg/BUILD.bazel +++ b/pkg/BUILD.bazel @@ -208,6 +208,7 @@ cc_dist_library( name = "upb", tags = ["manual"], deps = [ + "//upb:generated_code_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me", "//upb/json", "//upb/message:compare", "//upb/message:copy", diff --git a/protobuf.bzl b/protobuf.bzl index 888e978726..a41c8f8acc 100644 --- a/protobuf.bzl +++ b/protobuf.bzl @@ -267,7 +267,6 @@ _proto_gen = rule( default = "all", ), }, - output_to_genfiles = True, implementation = _proto_gen_impl, ) diff --git a/protos/bazel/upb_cc_proto_library.bzl b/protos/bazel/upb_cc_proto_library.bzl index 105f8c0089..f071266ac4 100644 --- a/protos/bazel/upb_cc_proto_library.bzl +++ b/protos/bazel/upb_cc_proto_library.bzl @@ -289,7 +289,6 @@ _upb_cc_proto_library_aspect = aspect( ) upb_cc_proto_library = rule( - output_to_genfiles = True, implementation = _upb_cc_proto_rule_impl, attrs = { "deps": attr.label_list( diff --git a/protos/protos.h b/protos/protos.h index 5c57aae163..0bac4b683e 100644 --- a/protos/protos.h +++ b/protos/protos.h @@ -137,6 +137,10 @@ struct PrivateAccess { static auto CProxy(const upb_Message* p, upb_Arena* arena) { return typename T::CProxy(p, arena); } + template + static auto CreateMessage(upb_Arena* arena) { + return typename T::Proxy(upb_Message_New(T::minitable(), arena), arena); + } }; template diff --git a/python/dist/dist.bzl b/python/dist/dist.bzl index 75c21c31c3..061125ede6 100644 --- a/python/dist/dist.bzl +++ b/python/dist/dist.bzl @@ -113,7 +113,6 @@ def _py_dist_module_impl(ctx): ] py_dist_module = rule( - output_to_genfiles = True, implementation = _py_dist_module_impl, attrs = { "module_name": attr.string(mandatory = True), diff --git a/python/google/protobuf/internal/descriptor_pool_test.py b/python/google/protobuf/internal/descriptor_pool_test.py index 8f3bdeb2f9..bfe1e154dc 100644 --- a/python/google/protobuf/internal/descriptor_pool_test.py +++ b/python/google/protobuf/internal/descriptor_pool_test.py @@ -1145,13 +1145,17 @@ class FeatureSetDefaults(unittest.TestCase): ) defaults.defaults[0].features.Extensions[ unittest_features_pb2.test - ].int_file_feature = 9 + ].file_feature = unittest_features_pb2.VALUE9 pool.SetFeatureSetDefaults(defaults) file_desc = descriptor_pb2.FileDescriptorProto(name='some/file.proto') file = pool.AddSerializedFile(file_desc.SerializeToString()) self.assertTrue( file._GetFeatures().HasExtension(unittest_features_pb2.test) ) + self.assertEqual( + file._GetFeatures().Extensions[unittest_features_pb2.test].file_feature, + unittest_features_pb2.VALUE9, + ) def testInvalidType(self): pool = descriptor_pool.DescriptorPool() diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py index 18779f80fd..70cff8fe36 100755 --- a/python/google/protobuf/internal/descriptor_test.py +++ b/python/google/protobuf/internal/descriptor_test.py @@ -1372,14 +1372,14 @@ def GetTestFeature(desc): return ( desc._GetFeatures() .Extensions[unittest_features_pb2.test] - .int_multiple_feature + .multiple_feature ) def SetTestFeature(proto, value): proto.options.features.Extensions[ unittest_features_pb2.test - ].int_multiple_feature = value + ].multiple_feature = value @testing_refleaks.TestCase @@ -1462,7 +1462,7 @@ class FeatureInheritanceTest(unittest.TestCase): ) defaults.defaults[0].features.Extensions[ unittest_features_pb2.test - ].int_multiple_feature = 1 + ].multiple_feature = 1 ret.pool.SetFeatureSetDefaults(defaults) ret.file = ret.pool.AddSerializedFile(self.file_proto.SerializeToString()) diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py index b66d96010b..68f1999b16 100755 --- a/python/google/protobuf/internal/message_test.py +++ b/python/google/protobuf/internal/message_test.py @@ -549,6 +549,15 @@ class MessageTest(unittest.TestCase): self.assertEqual([4, 3, 2, 1], [m.bb for m in msg.repeated_nested_message[::-1]]) + def testSortEmptyRepeated(self, message_module): + message = message_module.NestedTestAllTypes() + self.assertFalse(message.HasField('child')) + self.assertFalse(message.HasField('payload')) + message.child.repeated_child.sort() + message.payload.repeated_int32.sort() + self.assertFalse(message.HasField('child')) + self.assertFalse(message.HasField('payload')) + def testSortingRepeatedScalarFieldsDefaultComparator(self, message_module): """Check some different types with the default comparator.""" message = message_module.TestAllTypes() diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py index d5772d3d3e..d9d9d00f33 100644 --- a/python/google/protobuf/internal/text_format_test.py +++ b/python/google/protobuf/internal/text_format_test.py @@ -2299,6 +2299,17 @@ class TokenizerTest(unittest.TestCase): tokenizer = text_format.Tokenizer(text.splitlines(), skip_comments=False) tokenizer.ConsumeString() + def testGroupName(self): + grp = unittest_pb2.TestGroupExtension() + grp.Extensions[unittest_pb2.TestNestedExtension.optionalgroup_extension].a = 6 + self.assertEqual('[protobuf_unittest.TestNestedExtension.optionalgroup_extension] {\n a: 6\n}\n', str(grp)) + + msg = unittest_pb2.TestAllTypes( + repeatedgroup=[unittest_pb2.TestAllTypes.RepeatedGroup(a=1)]) + if api_implementation.Type() == 'upb': + self.assertEqual('repeatedgroup {\n a: 1\n}\n', str(msg)) + else: + self.assertEqual('RepeatedGroup {\n a: 1\n}\n', str(msg)) # Tests for pretty printer functionality. @_parameterized.parameters((unittest_pb2), (unittest_proto3_arena_pb2)) diff --git a/python/google/protobuf/internal/well_known_types.py b/python/google/protobuf/internal/well_known_types.py index 59e99e05d1..8a0a3b13dd 100644 --- a/python/google/protobuf/internal/well_known_types.py +++ b/python/google/protobuf/internal/well_known_types.py @@ -400,7 +400,7 @@ class Duration(object): self.seconds = seconds self.nanos = 0 - def ToTimedelta(self): + def ToTimedelta(self) -> datetime.timedelta: """Converts Duration to timedelta.""" return datetime.timedelta( seconds=self.seconds, microseconds=_RoundTowardZero( diff --git a/python/google/protobuf/runtime_version.py b/python/google/protobuf/runtime_version.py index 2f2464b667..519b1a3088 100644 --- a/python/google/protobuf/runtime_version.py +++ b/python/google/protobuf/runtime_version.py @@ -89,7 +89,7 @@ def ValidateProtobufRuntimeVersion( f' cannot be older than the linked gencode version. {error_prompt}' ) - if gen_suffix is not SUFFIX: + if gen_suffix != SUFFIX: raise VersionError( 'Detected mismatched Protobuf Gencode/Runtime version suffixes when' f' loading {location}: gencode {gen_version} runtime {version}.' diff --git a/python/repeated.c b/python/repeated.c index 57e347939b..7940b4d36f 100644 --- a/python/repeated.c +++ b/python/repeated.c @@ -473,11 +473,14 @@ static PyObject* PyUpb_RepeatedContainer_Sort(PyObject* pself, PyObject* args, } } + if (PyUpb_RepeatedContainer_Length(pself) == 0) Py_RETURN_NONE; + PyObject* ret = NULL; PyObject* full_slice = NULL; PyObject* list = NULL; PyObject* m = NULL; PyObject* res = NULL; + if ((full_slice = PySlice_New(NULL, NULL, NULL)) && (list = PyUpb_RepeatedContainer_Subscript(pself, full_slice)) && (m = PyObject_GetAttrString(list, "sort")) && diff --git a/ruby/BUILD.bazel b/ruby/BUILD.bazel index 087a9c5f9d..9f85d45b46 100755 --- a/ruby/BUILD.bazel +++ b/ruby/BUILD.bazel @@ -113,6 +113,8 @@ internal_copy_files( srcs = [ "//src/google/protobuf:test_messages_proto2.proto", "//src/google/protobuf:test_messages_proto3.proto", + "//src/google/protobuf/editions:golden/test_messages_proto2_editions.proto", + "//src/google/protobuf/editions:golden/test_messages_proto3_editions.proto", ], strip_prefix = "src", ) @@ -232,12 +234,12 @@ filegroup( conformance_test( name = "conformance_test", failure_list = "//conformance:failure_list_ruby.txt", + maximum_edition = "2023", target_compatible_with = select({ ":ruby_native": [], "//conditions:default": ["@platforms//:incompatible"], }), testee = "//conformance:conformance_ruby", - text_format_failure_list = "//conformance:text_format_failure_list_ruby.txt", ) conformance_test( @@ -246,23 +248,23 @@ conformance_test( "PROTOCOL_BUFFERS_RUBY_IMPLEMENTATION": "ffi", }, failure_list = "//conformance:failure_list_ruby.txt", + maximum_edition = "2023", target_compatible_with = select({ ":ruby_ffi": [], "//conditions:default": ["@platforms//:incompatible"], }), testee = "//conformance:conformance_ruby", - text_format_failure_list = "//conformance:text_format_failure_list_ruby.txt", ) conformance_test( name = "conformance_test_jruby", failure_list = "//conformance:failure_list_jruby.txt", + maximum_edition = "2023", target_compatible_with = select({ ":jruby_native": [], "//conditions:default": ["@platforms//:incompatible"], }), testee = "//conformance:conformance_ruby", - text_format_failure_list = "//conformance:text_format_failure_list_jruby.txt", ) conformance_test( @@ -271,12 +273,12 @@ conformance_test( "PROTOCOL_BUFFERS_RUBY_IMPLEMENTATION": "ffi", }, failure_list = "//conformance:failure_list_jruby_ffi.txt", + maximum_edition = "2023", target_compatible_with = select({ ":jruby_ffi": [], "//conditions:default": ["@platforms//:incompatible"], }), testee = "//conformance:conformance_ruby", - text_format_failure_list = "//conformance:text_format_failure_list_jruby.txt", ) ################################################################################ diff --git a/ruby/Rakefile b/ruby/Rakefile index 6d842917c3..92118af99c 100644 --- a/ruby/Rakefile +++ b/ruby/Rakefile @@ -22,11 +22,14 @@ well_known_protos = %w[ test_protos = %w[ tests/basic_test.proto + tests/basic_test_features.proto tests/basic_test_proto2.proto tests/generated_code.proto tests/generated_code_proto2.proto + tests/generated_code_editions.proto tests/multi_level_nesting_test.proto tests/repeated_field_test.proto + tests/service_test.proto tests/stress.proto tests/test_import.proto tests/test_import_proto2.proto diff --git a/ruby/ext/google/protobuf_c/defs.c b/ruby/ext/google/protobuf_c/defs.c index 9141c7bd08..5ef73d5ac9 100644 --- a/ruby/ext/google/protobuf_c/defs.c +++ b/ruby/ext/google/protobuf_c/defs.c @@ -23,6 +23,9 @@ static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_EnumDef* def); static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_FieldDef* def); static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_FileDef* def); static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_OneofDef* def); +static VALUE get_servicedef_obj(VALUE descriptor_pool, + const upb_ServiceDef* def); +static VALUE get_methoddef_obj(VALUE descriptor_pool, const upb_MethodDef* def); // A distinct object that is not accessible from Ruby. We use this as a // constructor argument to enforce that certain objects cannot be created from @@ -153,6 +156,7 @@ static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) { const upb_MessageDef* msgdef; const upb_EnumDef* enumdef; const upb_FieldDef* fielddef; + const upb_ServiceDef* servicedef; msgdef = upb_DefPool_FindMessageByName(self->symtab, name_str); if (msgdef) { @@ -169,6 +173,11 @@ static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) { return get_enumdef_obj(_self, enumdef); } + servicedef = upb_DefPool_FindServiceByName(self->symtab, name_str); + if (servicedef) { + return get_servicedef_obj(_self, servicedef); + } + return Qnil; } @@ -257,7 +266,20 @@ static VALUE decode_options(VALUE self, const char* option_type, int size, VALUE desc_rb = get_msgdef_obj(descriptor_pool, msgdef); const Descriptor* desc = ruby_to_Descriptor(desc_rb); - options_rb = Message_decode_bytes(size, bytes, 0, desc->klass, true); + options_rb = Message_decode_bytes(size, bytes, 0, desc->klass, false); + + // Strip features from the options proto to keep it internal. + const upb_MessageDef* decoded_desc = NULL; + upb_Message* options = Message_GetMutable(options_rb, &decoded_desc); + PBRUBY_ASSERT(options != NULL); + PBRUBY_ASSERT(decoded_desc == msgdef); + const upb_FieldDef* field = + upb_MessageDef_FindFieldByName(decoded_desc, "features"); + PBRUBY_ASSERT(field != NULL); + upb_Message_ClearFieldByDef(options, field); + + Message_freeze(options_rb); + rb_ivar_set(self, options_instancevar_interned, options_rb); return options_rb; } @@ -1294,6 +1316,298 @@ static void EnumDescriptor_register(VALUE module) { cEnumDescriptor = klass; } +// ----------------------------------------------------------------------------- +// ServiceDescriptor +// ----------------------------------------------------------------------------- + +typedef struct { + const upb_ServiceDef* servicedef; + // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() + // macro to update VALUE references, as to trigger write barriers. + VALUE module; // begins as nil + VALUE descriptor_pool; // Owns the upb_ServiceDef. +} ServiceDescriptor; + +static VALUE cServiceDescriptor = Qnil; + +static void ServiceDescriptor_mark(void* _self) { + ServiceDescriptor* self = _self; + rb_gc_mark(self->module); + rb_gc_mark(self->descriptor_pool); +} + +static const rb_data_type_t ServiceDescriptor_type = { + "Google::Protobuf::ServicDescriptor", + {ServiceDescriptor_mark, RUBY_DEFAULT_FREE, NULL}, + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, +}; + +static ServiceDescriptor* ruby_to_ServiceDescriptor(VALUE val) { + ServiceDescriptor* ret; + TypedData_Get_Struct(val, ServiceDescriptor, &ServiceDescriptor_type, ret); + return ret; +} + +static VALUE ServiceDescriptor_alloc(VALUE klass) { + ServiceDescriptor* self = ALLOC(ServiceDescriptor); + VALUE ret = TypedData_Wrap_Struct(klass, &ServiceDescriptor_type, self); + self->servicedef = NULL; + self->module = Qnil; + self->descriptor_pool = Qnil; + return ret; +} + +/* + * call-seq: + * ServiceDescriptor.new(c_only_cookie, ptr) => ServiceDescriptor + * + * Creates a descriptor wrapper object. May only be called from C. + */ +static VALUE ServiceDescriptor_initialize(VALUE _self, VALUE cookie, + VALUE descriptor_pool, VALUE ptr) { + ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self); + + if (cookie != c_only_cookie) { + rb_raise(rb_eRuntimeError, + "Descriptor objects may not be created from Ruby."); + } + + RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool); + self->servicedef = (const upb_ServiceDef*)NUM2ULL(ptr); + + return Qnil; +} + +/* + * call-seq: + * ServiceDescriptor.name => name + * + * Returns the name of this service. + */ +static VALUE ServiceDescriptor_name(VALUE _self) { + ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self); + return rb_str_maybe_null(upb_ServiceDef_FullName(self->servicedef)); +} + +/* + * call-seq: + * ServiceDescriptor.file_descriptor + * + * Returns the FileDescriptor object this service belongs to. + */ +static VALUE ServiceDescriptor_file_descriptor(VALUE _self) { + ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self); + return get_filedef_obj(self->descriptor_pool, + upb_ServiceDef_File(self->servicedef)); +} + +/* + * call-seq: + * ServiceDescriptor.each(&block) + * + * Iterates over methods in this service, yielding to the block on each one. + */ +static VALUE ServiceDescriptor_each(VALUE _self) { + ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self); + + int n = upb_ServiceDef_MethodCount(self->servicedef); + for (int i = 0; i < n; i++) { + const upb_MethodDef* method = upb_ServiceDef_Method(self->servicedef, i); + VALUE obj = get_methoddef_obj(self->descriptor_pool, method); + rb_yield(obj); + } + return Qnil; +} + +/* + * call-seq: + * ServiceDescriptor.options => options + * + * Returns the `ServiceOptions` for this `ServiceDescriptor`. + */ +static VALUE ServiceDescriptor_options(VALUE _self) { + ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self); + const google_protobuf_ServiceOptions* opts = + upb_ServiceDef_Options(self->servicedef); + upb_Arena* arena = upb_Arena_New(); + size_t size; + char* serialized = + google_protobuf_ServiceOptions_serialize(opts, arena, &size); + VALUE service_options = decode_options(_self, "ServiceOptions", size, + serialized, self->descriptor_pool); + upb_Arena_Free(arena); + return service_options; +} + +static void ServiceDescriptor_register(VALUE module) { + VALUE klass = rb_define_class_under(module, "ServiceDescriptor", rb_cObject); + rb_define_alloc_func(klass, ServiceDescriptor_alloc); + rb_define_method(klass, "initialize", ServiceDescriptor_initialize, 3); + rb_define_method(klass, "name", ServiceDescriptor_name, 0); + rb_define_method(klass, "each", ServiceDescriptor_each, 0); + rb_define_method(klass, "file_descriptor", ServiceDescriptor_file_descriptor, + 0); + rb_define_method(klass, "options", ServiceDescriptor_options, 0); + rb_include_module(klass, rb_mEnumerable); + rb_gc_register_address(&cServiceDescriptor); + cServiceDescriptor = klass; +} + +// ----------------------------------------------------------------------------- +// MethodDescriptor +// ----------------------------------------------------------------------------- + +typedef struct { + const upb_MethodDef* methoddef; + // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() + // macro to update VALUE references, as to trigger write barriers. + VALUE module; // begins as nil + VALUE descriptor_pool; // Owns the upb_MethodDef. +} MethodDescriptor; + +static VALUE cMethodDescriptor = Qnil; + +static void MethodDescriptor_mark(void* _self) { + MethodDescriptor* self = _self; + rb_gc_mark(self->module); + rb_gc_mark(self->descriptor_pool); +} + +static const rb_data_type_t MethodDescriptor_type = { + "Google::Protobuf::MethodDescriptor", + {MethodDescriptor_mark, RUBY_DEFAULT_FREE, NULL}, + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, +}; + +static MethodDescriptor* ruby_to_MethodDescriptor(VALUE val) { + MethodDescriptor* ret; + TypedData_Get_Struct(val, MethodDescriptor, &MethodDescriptor_type, ret); + return ret; +} + +static VALUE MethodDescriptor_alloc(VALUE klass) { + MethodDescriptor* self = ALLOC(MethodDescriptor); + VALUE ret = TypedData_Wrap_Struct(klass, &MethodDescriptor_type, self); + self->methoddef = NULL; + self->module = Qnil; + self->descriptor_pool = Qnil; + return ret; +} + +/* + * call-seq: + * MethodDescriptor.new(c_only_cookie, ptr) => MethodDescriptor + * + * Creates a descriptor wrapper object. May only be called from C. + */ +static VALUE MethodDescriptor_initialize(VALUE _self, VALUE cookie, + VALUE descriptor_pool, VALUE ptr) { + MethodDescriptor* self = ruby_to_MethodDescriptor(_self); + + if (cookie != c_only_cookie) { + rb_raise(rb_eRuntimeError, + "Descriptor objects may not be created from Ruby."); + } + + RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool); + self->methoddef = (const upb_ServiceDef*)NUM2ULL(ptr); + + return Qnil; +} + +/* + * call-seq: + * MethodDescriptor.name => name + * + * Returns the name of this method + */ +static VALUE MethodDescriptor_name(VALUE _self) { + MethodDescriptor* self = ruby_to_MethodDescriptor(_self); + return rb_str_maybe_null(upb_MethodDef_Name(self->methoddef)); +} + +/* + * call-seq: + * MethodDescriptor.options => options + * + * Returns the `MethodOptions` for this `MethodDescriptor`. + */ +static VALUE MethodDescriptor_options(VALUE _self) { + MethodDescriptor* self = ruby_to_MethodDescriptor(_self); + const google_protobuf_MethodOptions* opts = + upb_MethodDef_Options(self->methoddef); + upb_Arena* arena = upb_Arena_New(); + size_t size; + char* serialized = + google_protobuf_MethodOptions_serialize(opts, arena, &size); + VALUE method_options = decode_options(_self, "MethodOptions", size, + serialized, self->descriptor_pool); + upb_Arena_Free(arena); + return method_options; +} + +/* + * call-seq: + * MethodDescriptor.input_type => Descriptor + * + * Returns the `Descriptor` for the request message type of this method + */ +static VALUE MethodDescriptor_input_type(VALUE _self) { + MethodDescriptor* self = ruby_to_MethodDescriptor(_self); + const upb_MessageDef* type = upb_MethodDef_InputType(self->methoddef); + return get_msgdef_obj(self->descriptor_pool, type); +} + +/* + * call-seq: + * MethodDescriptor.output_type => Descriptor + * + * Returns the `Descriptor` for the response message type of this method + */ +static VALUE MethodDescriptor_output_type(VALUE _self) { + MethodDescriptor* self = ruby_to_MethodDescriptor(_self); + const upb_MessageDef* type = upb_MethodDef_OutputType(self->methoddef); + return get_msgdef_obj(self->descriptor_pool, type); +} + +/* + * call-seq: + * MethodDescriptor.client_streaming => bool + * + * Returns whether or not this is a streaming request method + */ +static VALUE MethodDescriptor_client_streaming(VALUE _self) { + MethodDescriptor* self = ruby_to_MethodDescriptor(_self); + return upb_MethodDef_ClientStreaming(self->methoddef) ? Qtrue : Qfalse; +} + +/* + * call-seq: + * MethodDescriptor.server_streaming => bool + * + * Returns whether or not this is a streaming response method + */ +static VALUE MethodDescriptor_server_streaming(VALUE _self) { + MethodDescriptor* self = ruby_to_MethodDescriptor(_self); + return upb_MethodDef_ServerStreaming(self->methoddef) ? Qtrue : Qfalse; +} + +static void MethodDescriptor_register(VALUE module) { + VALUE klass = rb_define_class_under(module, "MethodDescriptor", rb_cObject); + rb_define_alloc_func(klass, MethodDescriptor_alloc); + rb_define_method(klass, "initialize", MethodDescriptor_initialize, 3); + rb_define_method(klass, "name", MethodDescriptor_name, 0); + rb_define_method(klass, "options", MethodDescriptor_options, 0); + rb_define_method(klass, "input_type", MethodDescriptor_input_type, 0); + rb_define_method(klass, "output_type", MethodDescriptor_output_type, 0); + rb_define_method(klass, "client_streaming", MethodDescriptor_client_streaming, + 0); + rb_define_method(klass, "server_streaming", MethodDescriptor_server_streaming, + 0); + rb_gc_register_address(&cMethodDescriptor); + cMethodDescriptor = klass; +} + static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) { DescriptorPool* descriptor_pool = ruby_to_DescriptorPool(_descriptor_pool); VALUE key = ULL2NUM((intptr_t)ptr); @@ -1335,6 +1649,16 @@ static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_OneofDef* def) { return get_def_obj(descriptor_pool, def, cOneofDescriptor); } +static VALUE get_servicedef_obj(VALUE descriptor_pool, + const upb_ServiceDef* def) { + return get_def_obj(descriptor_pool, def, cServiceDescriptor); +} + +static VALUE get_methoddef_obj(VALUE descriptor_pool, + const upb_MethodDef* def) { + return get_def_obj(descriptor_pool, def, cMethodDescriptor); +} + // ----------------------------------------------------------------------------- // Shared functions // ----------------------------------------------------------------------------- @@ -1410,6 +1734,8 @@ void Defs_register(VALUE module) { FieldDescriptor_register(module); OneofDescriptor_register(module); EnumDescriptor_register(module); + ServiceDescriptor_register(module); + MethodDescriptor_register(module); rb_gc_register_address(&c_only_cookie); c_only_cookie = rb_class_new_instance(0, NULL, rb_cObject); diff --git a/ruby/ext/google/protobuf_c/glue.c b/ruby/ext/google/protobuf_c/glue.c index e51e364279..3c84d7fb47 100644 --- a/ruby/ext/google/protobuf_c/glue.c +++ b/ruby/ext/google/protobuf_c/glue.c @@ -54,3 +54,19 @@ char* FieldDescriptor_serialized_options(const upb_FieldDef* fielddef, char* serialized = google_protobuf_FieldOptions_serialize(opts, arena, size); return serialized; } + +char* ServiceDescriptor_serialized_options(const upb_ServiceDef* servicedef, + size_t* size, upb_Arena* arena) { + const google_protobuf_ServiceOptions* opts = + upb_ServiceDef_Options(servicedef); + char* serialized = + google_protobuf_ServiceOptions_serialize(opts, arena, size); + return serialized; +} + +char* MethodDescriptor_serialized_options(const upb_MethodDef* methoddef, + size_t* size, upb_Arena* arena) { + const google_protobuf_MethodOptions* opts = upb_MethodDef_Options(methoddef); + char* serialized = google_protobuf_MethodOptions_serialize(opts, arena, size); + return serialized; +} diff --git a/ruby/ext/google/protobuf_c/ruby-upb.c b/ruby/ext/google/protobuf_c/ruby-upb.c index f109937eb6..4f015970fb 100644 --- a/ruby/ext/google/protobuf_c/ruby-upb.c +++ b/ruby/ext/google/protobuf_c/ruby-upb.c @@ -305,10 +305,10 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); /* Disable proto2 arena behavior (TEMPORARY) **********************************/ -#ifdef UPB_DISABLE_PROTO2_ENUM_CHECKING -#define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 1 +#ifdef UPB_DISABLE_CLOSED_ENUM_CHECKING +#define UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN 1 #else -#define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 0 +#define UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN 0 #endif #if defined(__cplusplus) @@ -4044,6 +4044,10 @@ static void* upb_global_allocfunc(upb_alloc* alloc, void* ptr, size_t oldsize, upb_alloc upb_alloc_global = {&upb_global_allocfunc}; +#ifdef UPB_TRACING_ENABLED +#include +#endif + #include #include @@ -4150,6 +4154,38 @@ static bool _upb_ArenaInternal_HasInitialBlock(upb_ArenaInternal* ai) { return ai->block_alloc & 0x1; } +#ifdef UPB_TRACING_ENABLED +static void (*_init_arena_trace_handler)(const upb_Arena*, size_t size) = NULL; +static void (*_fuse_arena_trace_handler)(const upb_Arena*, + const upb_Arena*) = NULL; +static void (*_free_arena_trace_handler)(const upb_Arena*) = NULL; + +void upb_Arena_SetTraceHandler( + void (*initArenaTraceHandler)(const upb_Arena*, size_t size), + void (*fuseArenaTraceHandler)(const upb_Arena*, const upb_Arena*), + void (*freeArenaTraceHandler)(const upb_Arena*)) { + _init_arena_trace_handler = initArenaTraceHandler; + _fuse_arena_trace_handler = fuseArenaTraceHandler; + _free_arena_trace_handler = freeArenaTraceHandler; +} + +void upb_Arena_LogInit(const upb_Arena* arena, size_t size) { + if (_init_arena_trace_handler) { + _init_arena_trace_handler(arena, size); + } +} +void upb_Arena_LogFuse(const upb_Arena* arena1, const upb_Arena* arena2) { + if (_fuse_arena_trace_handler) { + _fuse_arena_trace_handler(arena1, arena2); + } +} +void upb_Arena_LogFree(const upb_Arena* arena) { + if (_free_arena_trace_handler) { + _free_arena_trace_handler(arena); + } +} +#endif // UPB_TRACING_ENABLED + static upb_ArenaRoot _upb_Arena_FindRoot(upb_Arena* a) { upb_ArenaInternal* ai = upb_Arena_Internal(a); uintptr_t poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); @@ -4313,7 +4349,13 @@ upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) { n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_ArenaState)); if (UPB_UNLIKELY(n < sizeof(upb_ArenaState))) { +#ifdef UPB_TRACING_ENABLED + upb_Arena* ret = _upb_Arena_InitSlow(alloc); + upb_Arena_LogInit(ret, n); + return ret; +#else return _upb_Arena_InitSlow(alloc); +#endif } a = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), upb_ArenaState); @@ -4326,13 +4368,14 @@ upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) { a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 1); a->head.UPB_PRIVATE(ptr) = mem; a->head.UPB_PRIVATE(end) = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), char); - +#ifdef UPB_TRACING_ENABLED + upb_Arena_LogInit(&a->head, n); +#endif return &a->head; } static void _upb_Arena_DoFree(upb_ArenaInternal* ai) { UPB_ASSERT(_upb_Arena_RefCountFromTagged(ai->parent_or_count) == 1); - while (ai != NULL) { // Load first since arena itself is likely from one of its blocks. upb_ArenaInternal* next_arena = @@ -4363,6 +4406,9 @@ retry: // expensive then direct loads. As an optimization, we only do RMW ops // when we need to update things for other threads to see. if (poc == _upb_Arena_TaggedFromRefcount(1)) { +#ifdef UPB_TRACING_ENABLED + upb_Arena_LogFree(a); +#endif _upb_Arena_DoFree(ai); return; } @@ -4482,6 +4528,10 @@ static bool _upb_Arena_FixupRefs(upb_ArenaInternal* new_root, bool upb_Arena_Fuse(upb_Arena* a1, upb_Arena* a2) { if (a1 == a2) return true; // trivial fuse +#ifdef UPB_TRACING_ENABLED + upb_Arena_LogFuse(a1, a2); +#endif + upb_ArenaInternal* ai1 = upb_Arena_Internal(a1); upb_ArenaInternal* ai2 = upb_Arena_Internal(a2); @@ -11404,13 +11454,13 @@ bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need, static void (*_new_message_trace_handler)(const upb_MiniTable*, const upb_Arena*); -void upb_Message_SetNewMessageTraceHandler( +void UPB_PRIVATE(upb_Message_SetNewMessageTraceHandler)( void (*new_message_trace_handler)(const upb_MiniTable*, const upb_Arena*)) { _new_message_trace_handler = new_message_trace_handler; } -void upb_Message_LogNewMessage(const upb_MiniTable* mini_table, - const upb_Arena* arena) { +void UPB_PRIVATE(upb_Message_LogNewMessage)(const upb_MiniTable* mini_table, + const upb_Arena* arena) { if (_new_message_trace_handler) { _new_message_trace_handler(mini_table, arena); } @@ -12446,7 +12496,11 @@ const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i) { } bool upb_EnumDef_IsClosed(const upb_EnumDef* e) { - if (UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3) return false; + if (UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN) return false; + return upb_EnumDef_IsSpecifiedAsClosed(e); +} + +bool upb_EnumDef_IsSpecifiedAsClosed(const upb_EnumDef* e) { return UPB_DESC(FeatureSet_enum_type)(e->resolved_features) == UPB_DESC(FeatureSet_CLOSED); } @@ -12752,15 +12806,10 @@ static void create_enumvaldef(upb_DefBuilder* ctx, const char* prefix, static void _upb_EnumValueDef_CheckZeroValue(upb_DefBuilder* ctx, const upb_EnumDef* e, const upb_EnumValueDef* v, int n) { - if (upb_EnumDef_IsClosed(e) || n == 0 || v[0].number == 0) return; - - // When the special UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 is enabled, we have to - // exempt proto2 enums from this check, even when we are treating them as + // When the special UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN is enabled, we have to + // exempt closed enums from this check, even when we are treating them as // open. - if (UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 && - upb_FileDef_Syntax(upb_EnumDef_File(e)) == kUpb_Syntax_Proto2) { - return; - } + if (upb_EnumDef_IsSpecifiedAsClosed(e) || n == 0 || v[0].number == 0) return; _upb_DefBuilder_Errf(ctx, "for open enums, the first value must be zero (%s)", upb_EnumDef_FullName(e)); @@ -12954,6 +13003,10 @@ upb_FieldType upb_FieldDef_Type(const upb_FieldDef* f) { uint32_t upb_FieldDef_Index(const upb_FieldDef* f) { return f->index_; } +uint32_t upb_FieldDef_LayoutIndex(const upb_FieldDef* f) { + return f->layout_index; +} + upb_Label upb_FieldDef_Label(const upb_FieldDef* f) { // TODO: remove once we can deprecate kUpb_Label_Required. if (UPB_DESC(FeatureSet_field_presence)(f->resolved_features) == @@ -16117,7 +16170,7 @@ upb_ServiceDef* _upb_ServiceDefs_New(upb_DefBuilder* ctx, int n, #undef UPB_ASAN #undef UPB_ASAN_GUARD_SIZE #undef UPB_CLANG_ASAN -#undef UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 +#undef UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN #undef UPB_DEPRECATED #undef UPB_GNUC_MIN #undef UPB_DESCRIPTOR_UPB_H_FILENAME diff --git a/ruby/ext/google/protobuf_c/ruby-upb.h b/ruby/ext/google/protobuf_c/ruby-upb.h index c2fa025785..fb7684be5f 100755 --- a/ruby/ext/google/protobuf_c/ruby-upb.h +++ b/ruby/ext/google/protobuf_c/ruby-upb.h @@ -1,5 +1,5 @@ // Ruby is still using proto3 enum semantics for proto2 -#define UPB_DISABLE_PROTO2_ENUM_CHECKING +#define UPB_DISABLE_CLOSED_ENUM_CHECKING /* Amalgamated source file */ /* @@ -306,10 +306,10 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); /* Disable proto2 arena behavior (TEMPORARY) **********************************/ -#ifdef UPB_DISABLE_PROTO2_ENUM_CHECKING -#define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 1 +#ifdef UPB_DISABLE_CLOSED_ENUM_CHECKING +#define UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN 1 #else -#define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 0 +#define UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN 0 #endif #if defined(__cplusplus) @@ -808,6 +808,14 @@ UPB_API_INLINE void* upb_Arena_Realloc(upb_Arena* a, void* ptr, size_t oldsize, UPB_API_INLINE void upb_Arena_ShrinkLast(upb_Arena* a, void* ptr, size_t oldsize, size_t size); +#ifdef UPB_TRACING_ENABLED +void upb_Arena_SetTraceHandler(void (*initArenaTraceHandler)(const upb_Arena*, + size_t size), + void (*fuseArenaTraceHandler)(const upb_Arena*, + const upb_Arena*), + void (*freeArenaTraceHandler)(const upb_Arena*)); +#endif + #ifdef __cplusplus } /* extern "C" */ #endif @@ -2444,17 +2452,17 @@ typedef struct upb_Message_Internal { } upb_Message_Internal; #ifdef UPB_TRACING_ENABLED -void upb_Message_SetNewMessageTraceHandler( +void UPB_PRIVATE(upb_Message_SetNewMessageTraceHandler)( void (*newMessageTraceHandler)(const upb_MiniTable*, const upb_Arena*)); -void upb_Message_LogNewMessage(const upb_MiniTable* mini_table, - const upb_Arena* arena); +void UPB_PRIVATE(upb_Message_LogNewMessage)(const upb_MiniTable* mini_table, + const upb_Arena* arena); #endif // Inline version upb_Message_New(), for internal use. UPB_INLINE struct upb_Message* _upb_Message_New(const upb_MiniTable* m, upb_Arena* a) { #ifdef UPB_TRACING_ENABLED - upb_Message_LogNewMessage(m, a); + UPB_PRIVATE(upb_Message_LogNewMessage)(m, a); #endif const int size = m->UPB_PRIVATE(size); struct upb_Message* msg = (struct upb_Message*)upb_Arena_Malloc(a, size); @@ -2971,12 +2979,6 @@ UPB_API_INLINE bool upb_Map_Set(upb_Map* map, upb_MessageValue key, UPB_API bool upb_Map_Delete(upb_Map* map, upb_MessageValue key, upb_MessageValue* val); -// (DEPRECATED and going away soon. Do not use.) -UPB_INLINE bool upb_Map_Delete2(upb_Map* map, upb_MessageValue key, - upb_MessageValue* val) { - return upb_Map_Delete(map, key, val); -} - // Map iteration: // // size_t iter = kUpb_Map_Begin; @@ -3077,6 +3079,18 @@ UPB_API void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m); // Returns whether a message has been frozen. UPB_API_INLINE bool upb_Message_IsFrozen(const upb_Message* msg); +#ifdef UPB_TRACING_ENABLED +UPB_INLINE void upb_Message_SetNewMessageTraceHandler( + void (*newMessageTraceHandler)(const upb_MiniTable* mini_table, + const upb_Arena* arena)) { + UPB_PRIVATE(upb_Message_SetNewMessageTraceHandler)(newMessageTraceHandler); +} +UPB_INLINE void upb_Message_LogNewMessage(const upb_MiniTable* mini_table, + const upb_Arena* arena) { + UPB_PRIVATE(upb_Message_LogNewMessage)(mini_table, arena); +} +#endif + #ifdef __cplusplus } /* extern "C" */ #endif @@ -11466,8 +11480,8 @@ const upb_FieldDef* upb_DefPool_FindExtensionByNumber(const upb_DefPool* s, const upb_MessageDef* m, int32_t fieldnum); -const upb_ServiceDef* upb_DefPool_FindServiceByName(const upb_DefPool* s, - const char* name); +UPB_API const upb_ServiceDef* upb_DefPool_FindServiceByName( + const upb_DefPool* s, const char* name); const upb_ServiceDef* upb_DefPool_FindServiceByNameWithSize( const upb_DefPool* s, const char* name, size_t size); @@ -11518,6 +11532,7 @@ UPB_API const upb_EnumValueDef* upb_EnumDef_FindValueByNumber( UPB_API const char* upb_EnumDef_FullName(const upb_EnumDef* e); bool upb_EnumDef_HasOptions(const upb_EnumDef* e); bool upb_EnumDef_IsClosed(const upb_EnumDef* e); +bool upb_EnumDef_IsSpecifiedAsClosed(const upb_EnumDef* e); // Creates a mini descriptor string for an enum, returns true on success. bool upb_EnumDef_MiniDescriptorEncode(const upb_EnumDef* e, upb_Arena* a, @@ -11646,6 +11661,7 @@ bool upb_FieldDef_IsString(const upb_FieldDef* f); UPB_API bool upb_FieldDef_IsSubMessage(const upb_FieldDef* f); UPB_API const char* upb_FieldDef_JsonName(const upb_FieldDef* f); UPB_API upb_Label upb_FieldDef_Label(const upb_FieldDef* f); +uint32_t upb_FieldDef_LayoutIndex(const upb_FieldDef* f); UPB_API const upb_MessageDef* upb_FieldDef_MessageSubDef(const upb_FieldDef* f); bool _upb_FieldDef_ValidateUtf8(const upb_FieldDef* f); @@ -11883,18 +11899,19 @@ UPB_API upb_WellKnown upb_MessageDef_WellKnownType(const upb_MessageDef* m); extern "C" { #endif -bool upb_MethodDef_ClientStreaming(const upb_MethodDef* m); +UPB_API bool upb_MethodDef_ClientStreaming(const upb_MethodDef* m); const char* upb_MethodDef_FullName(const upb_MethodDef* m); bool upb_MethodDef_HasOptions(const upb_MethodDef* m); int upb_MethodDef_Index(const upb_MethodDef* m); -const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m); -const char* upb_MethodDef_Name(const upb_MethodDef* m); -const UPB_DESC(MethodOptions) * upb_MethodDef_Options(const upb_MethodDef* m); +UPB_API const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m); +UPB_API const char* upb_MethodDef_Name(const upb_MethodDef* m); +UPB_API const UPB_DESC(MethodOptions) * + upb_MethodDef_Options(const upb_MethodDef* m); const UPB_DESC(FeatureSet) * upb_MethodDef_ResolvedFeatures(const upb_MethodDef* m); -const upb_MessageDef* upb_MethodDef_OutputType(const upb_MethodDef* m); -bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m); -const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m); +UPB_API const upb_MessageDef* upb_MethodDef_OutputType(const upb_MethodDef* m); +UPB_API bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m); +UPB_API const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m); #ifdef __cplusplus } /* extern "C" */ @@ -11955,16 +11972,17 @@ const UPB_DESC(FeatureSet*) extern "C" { #endif -const upb_FileDef* upb_ServiceDef_File(const upb_ServiceDef* s); +UPB_API const upb_FileDef* upb_ServiceDef_File(const upb_ServiceDef* s); const upb_MethodDef* upb_ServiceDef_FindMethodByName(const upb_ServiceDef* s, const char* name); -const char* upb_ServiceDef_FullName(const upb_ServiceDef* s); +UPB_API const char* upb_ServiceDef_FullName(const upb_ServiceDef* s); bool upb_ServiceDef_HasOptions(const upb_ServiceDef* s); int upb_ServiceDef_Index(const upb_ServiceDef* s); -const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, int i); -int upb_ServiceDef_MethodCount(const upb_ServiceDef* s); +UPB_API const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, + int i); +UPB_API int upb_ServiceDef_MethodCount(const upb_ServiceDef* s); const char* upb_ServiceDef_Name(const upb_ServiceDef* s); -const UPB_DESC(ServiceOptions) * +UPB_API const UPB_DESC(ServiceOptions) * upb_ServiceDef_Options(const upb_ServiceDef* s); const UPB_DESC(FeatureSet) * upb_ServiceDef_ResolvedFeatures(const upb_ServiceDef* s); @@ -14073,7 +14091,7 @@ upb_MethodDef* _upb_MethodDefs_New(upb_DefBuilder* ctx, int n, #undef UPB_ASAN #undef UPB_ASAN_GUARD_SIZE #undef UPB_CLANG_ASAN -#undef UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 +#undef UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN #undef UPB_DEPRECATED #undef UPB_GNUC_MIN #undef UPB_DESCRIPTOR_UPB_H_FILENAME diff --git a/ruby/lib/google/protobuf/ffi/descriptor.rb b/ruby/lib/google/protobuf/ffi/descriptor.rb index 3175d41355..1ccaf77a90 100644 --- a/ruby/lib/google/protobuf/ffi/descriptor.rb +++ b/ruby/lib/google/protobuf/ffi/descriptor.rb @@ -100,7 +100,9 @@ module Google size_ptr = ::FFI::MemoryPointer.new(:size_t, 1) temporary_arena = Google::Protobuf::FFI.create_arena buffer = Google::Protobuf::FFI.message_options(self, size_ptr, temporary_arena) - Google::Protobuf::MessageOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze).freeze + opts = Google::Protobuf::MessageOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze) + opts.clear_features() + opts.freeze end end diff --git a/ruby/lib/google/protobuf/ffi/descriptor_pool.rb b/ruby/lib/google/protobuf/ffi/descriptor_pool.rb index 96c7d09417..4dc177d582 100644 --- a/ruby/lib/google/protobuf/ffi/descriptor_pool.rb +++ b/ruby/lib/google/protobuf/ffi/descriptor_pool.rb @@ -16,6 +16,7 @@ module Google attach_function :lookup_enum, :upb_DefPool_FindEnumByName, [:DefPool, :string], EnumDescriptor attach_function :lookup_extension, :upb_DefPool_FindExtensionByName,[:DefPool, :string], FieldDescriptor attach_function :lookup_msg, :upb_DefPool_FindMessageByName, [:DefPool, :string], Descriptor + attach_function :lookup_service, :upb_DefPool_FindServiceByName, [:DefPool, :string], ServiceDescriptor # FileDescriptorProto attach_function :parse, :FileDescriptorProto_parse, [:binary_string, :size_t, Internal::Arena], :FileDescriptorProto @@ -54,7 +55,8 @@ module Google def lookup name Google::Protobuf::FFI.lookup_msg(@descriptor_pool, name) || Google::Protobuf::FFI.lookup_enum(@descriptor_pool, name) || - Google::Protobuf::FFI.lookup_extension(@descriptor_pool, name) + Google::Protobuf::FFI.lookup_extension(@descriptor_pool, name) || + Google::Protobuf::FFI.lookup_service(@descriptor_pool, name) end def self.generated_pool diff --git a/ruby/lib/google/protobuf/ffi/enum_descriptor.rb b/ruby/lib/google/protobuf/ffi/enum_descriptor.rb index e280e393a1..e7ce04dab0 100644 --- a/ruby/lib/google/protobuf/ffi/enum_descriptor.rb +++ b/ruby/lib/google/protobuf/ffi/enum_descriptor.rb @@ -84,7 +84,9 @@ module Google size_ptr = ::FFI::MemoryPointer.new(:size_t, 1) temporary_arena = Google::Protobuf::FFI.create_arena buffer = Google::Protobuf::FFI.enum_options(self, size_ptr, temporary_arena) - Google::Protobuf::EnumOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze).freeze + opts = Google::Protobuf::EnumOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze) + opts.clear_features() + opts.freeze end end diff --git a/ruby/lib/google/protobuf/ffi/ffi.rb b/ruby/lib/google/protobuf/ffi/ffi.rb index 765f04c2ba..2549fcb0a6 100644 --- a/ruby/lib/google/protobuf/ffi/ffi.rb +++ b/ruby/lib/google/protobuf/ffi/ffi.rb @@ -95,11 +95,6 @@ module Google :repeated ) - Syntax = enum( - :Proto2, 2, - :Proto3 - ) - # All the different kind of well known type messages. For simplicity of check, # number wrappers and string wrappers are grouped together. Make sure the # order and merber of these groups are not changed. diff --git a/ruby/lib/google/protobuf/ffi/field_descriptor.rb b/ruby/lib/google/protobuf/ffi/field_descriptor.rb index cbc1e82ac7..632692b75d 100644 --- a/ruby/lib/google/protobuf/ffi/field_descriptor.rb +++ b/ruby/lib/google/protobuf/ffi/field_descriptor.rb @@ -68,7 +68,7 @@ module Google end def label - @label ||= Google::Protobuf::FFI::Label[Google::Protobuf::FFI.get_label(self)] + @label ||= Google::Protobuf::FFI.get_label(self) end def default @@ -219,7 +219,9 @@ module Google size_ptr = ::FFI::MemoryPointer.new(:size_t, 1) temporary_arena = Google::Protobuf::FFI.create_arena buffer = Google::Protobuf::FFI.field_options(self, size_ptr, temporary_arena) - Google::Protobuf::FieldOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze).freeze + opts = Google::Protobuf::FieldOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze) + opts.clear_features() + opts.freeze end end diff --git a/ruby/lib/google/protobuf/ffi/file_descriptor.rb b/ruby/lib/google/protobuf/ffi/file_descriptor.rb index 2035b98efc..2a7bf87e6d 100644 --- a/ruby/lib/google/protobuf/ffi/file_descriptor.rb +++ b/ruby/lib/google/protobuf/ffi/file_descriptor.rb @@ -39,7 +39,9 @@ module Google size_ptr = ::FFI::MemoryPointer.new(:size_t, 1) temporary_arena = Google::Protobuf::FFI.create_arena buffer = Google::Protobuf::FFI.file_options(@file_def, size_ptr, temporary_arena) - Google::Protobuf::FileOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze).freeze + opts = Google::Protobuf::FileOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze) + opts.clear_features() + opts.freeze end end end diff --git a/ruby/lib/google/protobuf/ffi/internal/convert.rb b/ruby/lib/google/protobuf/ffi/internal/convert.rb index b1eb0005e2..cf8669329b 100644 --- a/ruby/lib/google/protobuf/ffi/internal/convert.rb +++ b/ruby/lib/google/protobuf/ffi/internal/convert.rb @@ -32,7 +32,7 @@ module Google raise TypeError.new "Invalid argument for boolean field '#{name}' (given #{value.class})." unless [TrueClass, FalseClass].include? value.class return_value[:bool_val] = value when :string - raise TypeError.new "Invalid argument for string field '#{name}' (given #{value.class})." unless [Symbol, String].include? value.class + raise TypeError.new "Invalid argument for string field '#{name}' (given #{value.class})." unless value.is_a?(String) or value.is_a?(Symbol) begin string_value = value.to_s.encode("UTF-8") rescue Encoding::UndefinedConversionError diff --git a/ruby/lib/google/protobuf/ffi/method_descriptor.rb b/ruby/lib/google/protobuf/ffi/method_descriptor.rb new file mode 100644 index 0000000000..b7bbf0af08 --- /dev/null +++ b/ruby/lib/google/protobuf/ffi/method_descriptor.rb @@ -0,0 +1,114 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2024 Google Inc. All rights reserved. +# +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file or at +# https://developers.google.com/open-source/licenses/bsd + +module Google + module Protobuf + class MethodDescriptor + attr :method_def, :descriptor_pool + + include Google::Protobuf::Internal::Convert + + # FFI Interface methods and setup + extend ::FFI::DataConverter + native_type ::FFI::Type::POINTER + + class << self + prepend Google::Protobuf::Internal::TypeSafety + include Google::Protobuf::Internal::PointerHelper + + # @param value [MethodDescriptor] MethodDescriptor to convert to an FFI native type + # @param _ [Object] Unused + def to_native(value, _) + method_def_ptr = value.nil? ? nil : value.instance_variable_get(:@method_def) + return ::FFI::Pointer::NULL if method_def_ptr.nil? + raise "Underlying method_def was null!" if method_def_ptr.null? + method_def_ptr + end + + ## + # @param service_def [::FFI::Pointer] MethodDef pointer to be wrapped + # @param _ [Object] Unused + def from_native(method_def, _ = nil) + return nil if method_def.nil? or method_def.null? + service_def = Google::Protobuf::FFI.raw_service_def_by_raw_method_def(method_def) + file_def = Google::Protobuf::FFI.file_def_by_raw_service_def(service_def) + descriptor_from_file_def(file_def, method_def) + end + end + + def self.new(*arguments, &block) + raise "Descriptor objects may not be created from Ruby." + end + + def to_s + inspect + end + + def inspect + "#{self.class.name}: #{name}" + end + + def name + @name ||= Google::Protobuf::FFI.get_method_name(self) + end + + def options + @options ||= begin + size_ptr = ::FFI::MemoryPointer.new(:size_t, 1) + temporary_arena = Google::Protobuf::FFI.create_arena + buffer = Google::Protobuf::FFI.method_options(self, size_ptr, temporary_arena) + Google::Protobuf::MethodOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze).freeze + end + end + + def input_type + @input_type ||= Google::Protobuf::FFI.method_input_type(self) + end + + def output_type + @output_type ||= Google::Protobuf::FFI.method_output_type(self) + end + + def client_streaming + @client_streaming ||= Google::Protobuf::FFI.method_client_streaming(self) + end + + def server_streaming + @server_streaming ||= Google::Protobuf::FFI.method_server_streaming(self) + end + + private + + def initialize(method_def, descriptor_pool) + @method_def = method_def + @descriptor_pool = descriptor_pool + end + + def self.private_constructor(method_def, descriptor_pool) + instance = allocate + instance.send(:initialize, method_def, descriptor_pool) + instance + end + + def c_type + @c_type ||= Google::Protobuf::FFI.get_c_type(self) + end + end + + class FFI + # MethodDef + attach_function :raw_service_def_by_raw_method_def, :upb_MethodDef_Service, [:pointer], :pointer + attach_function :get_method_name, :upb_MethodDef_Name, [MethodDescriptor], :string + attach_function :method_options, :MethodDescriptor_serialized_options, [MethodDescriptor, :pointer, Internal::Arena], :pointer + attach_function :method_input_type, :upb_MethodDef_InputType, [MethodDescriptor], Descriptor + attach_function :method_output_type, :upb_MethodDef_OutputType, [MethodDescriptor], Descriptor + attach_function :method_client_streaming, :upb_MethodDef_ClientStreaming, [MethodDescriptor], :bool + attach_function :method_server_streaming, :upb_MethodDef_ServerStreaming, [MethodDescriptor], :bool + end + end +end + diff --git a/ruby/lib/google/protobuf/ffi/oneof_descriptor.rb b/ruby/lib/google/protobuf/ffi/oneof_descriptor.rb index 934f8f0ac4..65050ef0ac 100644 --- a/ruby/lib/google/protobuf/ffi/oneof_descriptor.rb +++ b/ruby/lib/google/protobuf/ffi/oneof_descriptor.rb @@ -58,7 +58,9 @@ module Google size_ptr = ::FFI::MemoryPointer.new(:size_t, 1) temporary_arena = Google::Protobuf::FFI.create_arena buffer = Google::Protobuf::FFI.oneof_options(self, size_ptr, temporary_arena) - Google::Protobuf::OneofOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze).freeze + opts = Google::Protobuf::OneofOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze) + opts.clear_features() + opts.freeze end end diff --git a/ruby/lib/google/protobuf/ffi/service_descriptor.rb b/ruby/lib/google/protobuf/ffi/service_descriptor.rb new file mode 100644 index 0000000000..d8554d379d --- /dev/null +++ b/ruby/lib/google/protobuf/ffi/service_descriptor.rb @@ -0,0 +1,107 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2024 Google Inc. All rights reserved. +# +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file or at +# https://developers.google.com/open-source/licenses/bsd + +module Google + module Protobuf + class ServiceDescriptor + attr :service_def, :descriptor_pool + include Enumerable + + include Google::Protobuf::Internal::Convert + + # FFI Interface methods and setup + extend ::FFI::DataConverter + native_type ::FFI::Type::POINTER + + class << self + prepend Google::Protobuf::Internal::TypeSafety + include Google::Protobuf::Internal::PointerHelper + + # @param value [ServiceDescriptor] ServiceDescriptor to convert to an FFI native type + # @param _ [Object] Unused + def to_native(value, _) + service_def_ptr = value.nil? ? nil : value.instance_variable_get(:@service_def) + return ::FFI::Pointer::NULL if service_def_ptr.nil? + raise "Underlying service_def was null!" if service_def_ptr.null? + service_def_ptr + end + + ## + # @param service_def [::FFI::Pointer] ServiceDef pointer to be wrapped + # @param _ [Object] Unused + def from_native(service_def, _ = nil) + return nil if service_def.nil? or service_def.null? + file_def = Google::Protobuf::FFI.file_def_by_raw_service_def(service_def) + descriptor_from_file_def(file_def, service_def) + end + end + + def self.new(*arguments, &block) + raise "Descriptor objects may not be created from Ruby." + end + + def to_s + inspect + end + + def inspect + "#{self.class.name}: #{name}" + end + + def name + @name ||= Google::Protobuf::FFI.get_service_full_name(self) + end + + def file_descriptor + @descriptor_pool.send(:get_file_descriptor, Google::Protobuf::FFI.file_def_by_raw_service_def(@service_def)) + end + + def each &block + n = Google::Protobuf::FFI.method_count(self) + 0.upto(n-1) do |i| + yield(Google::Protobuf::FFI.get_method_by_index(self, i)) + end + nil + end + + def options + @options ||= begin + size_ptr = ::FFI::MemoryPointer.new(:size_t, 1) + temporary_arena = Google::Protobuf::FFI.create_arena + buffer = Google::Protobuf::FFI.service_options(self, size_ptr, temporary_arena) + Google::Protobuf::ServiceOptions.decode(buffer.read_string_length(size_ptr.read(:size_t)).force_encoding("ASCII-8BIT").freeze).freeze + end + end + + private + + def initialize(service_def, descriptor_pool) + @service_def = service_def + @descriptor_pool = descriptor_pool + end + + def self.private_constructor(service_def, descriptor_pool) + instance = allocate + instance.send(:initialize, service_def, descriptor_pool) + instance + end + + def c_type + @c_type ||= Google::Protobuf::FFI.get_c_type(self) + end + end + + class FFI + # ServiceDef + attach_function :file_def_by_raw_service_def, :upb_ServiceDef_File, [:pointer], :FileDef + attach_function :get_service_full_name, :upb_ServiceDef_FullName, [ServiceDescriptor], :string + attach_function :method_count, :upb_ServiceDef_MethodCount, [ServiceDescriptor], :int + attach_function :get_method_by_index, :upb_ServiceDef_Method, [ServiceDescriptor, :int], MethodDescriptor + attach_function :service_options, :ServiceDescriptor_serialized_options, [ServiceDescriptor, :pointer, Internal::Arena], :pointer + end + end +end diff --git a/ruby/lib/google/protobuf_ffi.rb b/ruby/lib/google/protobuf_ffi.rb index 0839b36d3f..6580df49a1 100644 --- a/ruby/lib/google/protobuf_ffi.rb +++ b/ruby/lib/google/protobuf_ffi.rb @@ -15,6 +15,8 @@ require 'google/protobuf/ffi/descriptor' require 'google/protobuf/ffi/enum_descriptor' require 'google/protobuf/ffi/field_descriptor' require 'google/protobuf/ffi/oneof_descriptor' +require 'google/protobuf/ffi/method_descriptor' +require 'google/protobuf/ffi/service_descriptor' require 'google/protobuf/ffi/descriptor_pool' require 'google/protobuf/ffi/file_descriptor' require 'google/protobuf/ffi/map' diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java index 7c01eb9270..017c9d5394 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java @@ -38,6 +38,8 @@ import com.google.protobuf.Descriptors.DescriptorValidationException; import com.google.protobuf.Descriptors.EnumDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.Descriptors.FileDescriptor; +import com.google.protobuf.Descriptors.ServiceDescriptor; +import com.google.protobuf.Descriptors.MethodDescriptor; import com.google.protobuf.ExtensionRegistry; import com.google.protobuf.InvalidProtocolBufferException; import java.util.ArrayList; @@ -73,6 +75,9 @@ public class RubyDescriptorPool extends RubyObject { cDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Descriptor"); cEnumDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::EnumDescriptor"); cFieldDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::FieldDescriptor"); + cServiceDescriptor = + (RubyClass) runtime.getClassFromPath("Google::Protobuf::ServiceDescriptor"); + cMethodDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::MethodDescriptor"); } public RubyDescriptorPool(Ruby runtime, RubyClass klazz) { @@ -156,6 +161,8 @@ public class RubyDescriptorPool extends RubyObject { registerDescriptor(context, message, packageName); for (FieldDescriptor fieldDescriptor : fd.getExtensions()) registerExtension(context, fieldDescriptor, packageName); + for (ServiceDescriptor serviceDescriptor : fd.getServices()) + registerService(context, serviceDescriptor, packageName); // Mark this as a loaded file fileDescriptors.add(fd); @@ -206,6 +213,18 @@ public class RubyDescriptorPool extends RubyObject { symtab.put(name, des); } + private void registerService( + ThreadContext context, ServiceDescriptor descriptor, String parentPath) { + String fullName = parentPath + descriptor.getName(); + RubyString name = context.runtime.newString(fullName); + RubyServiceDescriptor des = + (RubyServiceDescriptor) cServiceDescriptor.newInstance(context, Block.NULL_BLOCK); + des.setName(name); + // n.b. this will also construct the descriptors for the service's methods. + des.setDescriptor(context, descriptor, this); + symtab.putIfAbsent(name, des); + } + private FileDescriptor[] existingFileDescriptors() { return fileDescriptors.toArray(new FileDescriptor[fileDescriptors.size()]); } @@ -213,6 +232,8 @@ public class RubyDescriptorPool extends RubyObject { private static RubyClass cDescriptor; private static RubyClass cEnumDescriptor; private static RubyClass cFieldDescriptor; + private static RubyClass cServiceDescriptor; + private static RubyClass cMethodDescriptor; private static RubyDescriptorPool descriptorPool; private List fileDescriptors; diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java index 6f52e10067..189d881fbc 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java @@ -287,6 +287,8 @@ public class RubyFieldDescriptor extends RubyObject { private void calculateLabel(ThreadContext context) { if (descriptor.isRepeated()) { this.label = context.runtime.newSymbol("repeated"); + } else if (descriptor.isRequired()) { + this.label = context.runtime.newSymbol("required"); } else if (descriptor.isOptional()) { this.label = context.runtime.newSymbol("optional"); } else { diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMethodDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMethodDescriptor.java new file mode 100644 index 0000000000..1f33935793 --- /dev/null +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMethodDescriptor.java @@ -0,0 +1,160 @@ +/* + * Protocol Buffers - Google's data interchange format + * Copyright 2024 Google Inc. All rights reserved. + * https://developers.google.com/protocol-buffers/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.google.protobuf.jruby; + +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.Descriptors.MethodDescriptor; +import org.jruby.*; +import org.jruby.anno.JRubyClass; +import org.jruby.anno.JRubyMethod; +import org.jruby.runtime.Block; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.ThreadContext; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.anno.JRubyClass; +import org.jruby.anno.JRubyMethod; + +@JRubyClass(name = "MethoDescriptor") +public class RubyMethodDescriptor extends RubyObject { + public static void createRubyMethodDescriptor(Ruby runtime) { + RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf"); + RubyClass cMethodDescriptor = + protobuf.defineClassUnder( + "MethodDescriptor", + runtime.getObject(), + new ObjectAllocator() { + @Override + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + return new RubyMethodDescriptor(runtime, klazz); + } + }); + cMethodDescriptor.defineAnnotatedMethods(RubyMethodDescriptor.class); + } + + public RubyMethodDescriptor(Ruby runtime, RubyClass klazz) { + super(runtime, klazz); + } + + /* + * call-seq: + * MethodDescriptor.name => name + * + * Returns the name of this method + */ + @JRubyMethod(name = "name") + public IRubyObject getName(ThreadContext context) { + return context.runtime.newString(this.descriptor.getName()); + } + + /* + * call-seq: + * MethodDescriptor.options + * + * Returns the options set on this protobuf rpc method + */ + @JRubyMethod + public IRubyObject options(ThreadContext context) { + RubyDescriptorPool pool = (RubyDescriptorPool) RubyDescriptorPool.generatedPool(null, null); + RubyDescriptor methodOptionsDescriptor = + (RubyDescriptor) + pool.lookup(context, context.runtime.newString("google.protobuf.MethodOptions")); + RubyClass methodOptionsClass = (RubyClass) methodOptionsDescriptor.msgclass(context); + RubyMessage msg = (RubyMessage) methodOptionsClass.newInstance(context, Block.NULL_BLOCK); + return msg.decodeBytes( + context, + msg, + CodedInputStream.newInstance( + descriptor.getOptions().toByteString().toByteArray()), /*freeze*/ + true); + } + + /* + * call-seq: + * MethodDescriptor.input_type => Descriptor + * + * Returns the `Descriptor` for the request message type of this method + */ + @JRubyMethod(name = "input_type") + public IRubyObject getInputType(ThreadContext context) { + return this.pool.lookup( + context, context.runtime.newString(this.descriptor.getInputType().getFullName())); + } + + /* + * call-seq: + * MethodDescriptor.output_type => Descriptor + * + * Returns the `Descriptor` for the response message type of this method + */ + @JRubyMethod(name = "output_type") + public IRubyObject getOutputType(ThreadContext context) { + return this.pool.lookup( + context, context.runtime.newString(this.descriptor.getOutputType().getFullName())); + } + + /* + * call-seq: + * MethodDescriptor.client_streaming => bool + * + * Returns whether or not this is a streaming request method + */ + @JRubyMethod(name = "client_streaming") + public IRubyObject getClientStreaming(ThreadContext context) { + return this.descriptor.isClientStreaming() + ? context.runtime.getTrue() + : context.runtime.getFalse(); + } + + /* + * call-seq: + * MethodDescriptor.server_streaming => bool + * + * Returns whether or not this is a streaming response method + */ + @JRubyMethod(name = "server_streaming") + public IRubyObject getServerStreaming(ThreadContext context) { + return this.descriptor.isServerStreaming() + ? context.runtime.getTrue() + : context.runtime.getFalse(); + } + + protected void setDescriptor( + ThreadContext context, MethodDescriptor descriptor, RubyDescriptorPool pool) { + this.descriptor = descriptor; + this.pool = pool; + } + + private MethodDescriptor descriptor; + private IRubyObject name; + private RubyDescriptorPool pool; +} diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyServiceDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyServiceDescriptor.java new file mode 100644 index 0000000000..0a7a7e346e --- /dev/null +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyServiceDescriptor.java @@ -0,0 +1,156 @@ +/* + * Protocol Buffers - Google's data interchange format + * Copyright 2024 Google Inc. All rights reserved. + * https://developers.google.com/protocol-buffers/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.google.protobuf.jruby; + +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.Descriptors.MethodDescriptor; +import com.google.protobuf.Descriptors.ServiceDescriptor; +import java.util.LinkedHashMap; +import java.util.Map; +import org.jruby.*; +import org.jruby.anno.JRubyClass; +import org.jruby.anno.JRubyMethod; +import org.jruby.runtime.Block; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.ThreadContext; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.anno.JRubyClass; +import org.jruby.anno.JRubyMethod; + +@JRubyClass(name = "ServiceDescriptor") +public class RubyServiceDescriptor extends RubyObject { + public static void createRubyServiceDescriptor(Ruby runtime) { + RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf"); + RubyClass cServiceDescriptor = + protobuf.defineClassUnder( + "ServiceDescriptor", + runtime.getObject(), + new ObjectAllocator() { + @Override + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + return new RubyServiceDescriptor(runtime, klazz); + } + }); + cServiceDescriptor.includeModule(runtime.getEnumerable()); + cServiceDescriptor.defineAnnotatedMethods(RubyServiceDescriptor.class); + cMethodDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::MethodDescriptor"); + } + + public RubyServiceDescriptor(Ruby runtime, RubyClass klazz) { + super(runtime, klazz); + } + + /* + * call-seq: + * ServiceDescriptor.name => name + * + * Returns the name of this service type as a fully-qualified string (e.g., + * My.Package.Service). + */ + @JRubyMethod(name = "name") + public IRubyObject getName(ThreadContext context) { + return name; + } + + /* + * call-seq: + * ServiceDescriptor.file_descriptor + * + * Returns the FileDescriptor object this service belongs to. + */ + @JRubyMethod(name = "file_descriptor") + public IRubyObject getFileDescriptor(ThreadContext context) { + return RubyFileDescriptor.getRubyFileDescriptor(context, descriptor); + } + + /* + * call-seq: + * ServiceDescriptor.options + * + * Returns the options set on this protobuf service + */ + @JRubyMethod + public IRubyObject options(ThreadContext context) { + RubyDescriptorPool pool = (RubyDescriptorPool) RubyDescriptorPool.generatedPool(null, null); + RubyDescriptor serviceOptionsDescriptor = + (RubyDescriptor) + pool.lookup(context, context.runtime.newString("google.protobuf.ServiceOptions")); + RubyClass serviceOptionsClass = (RubyClass) serviceOptionsDescriptor.msgclass(context); + RubyMessage msg = (RubyMessage) serviceOptionsClass.newInstance(context, Block.NULL_BLOCK); + return msg.decodeBytes( + context, + msg, + CodedInputStream.newInstance( + descriptor.getOptions().toByteString().toByteArray()), /*freeze*/ + true); + } + + /* + * call-seq: + * ServiceDescriptor.each(&block) + * + * Iterates over methods in this service, yielding to the block on each one. + */ + @JRubyMethod(name = "each") + public IRubyObject each(ThreadContext context, Block block) { + for (Map.Entry entry : methodDescriptors.entrySet()) { + block.yield(context, entry.getValue()); + } + return context.nil; + } + + protected void setDescriptor( + ThreadContext context, ServiceDescriptor descriptor, RubyDescriptorPool pool) { + this.descriptor = descriptor; + + // Populate the methods (and preserve the order by using LinkedHashMap) + methodDescriptors = new LinkedHashMap(); + + for (MethodDescriptor methodDescriptor : descriptor.getMethods()) { + RubyMethodDescriptor md = + (RubyMethodDescriptor) cMethodDescriptor.newInstance(context, Block.NULL_BLOCK); + md.setDescriptor(context, methodDescriptor, pool); + methodDescriptors.put(context.runtime.newString(methodDescriptor.getName()), md); + } + } + + protected void setName(IRubyObject name) { + this.name = name; + } + + private static RubyClass cMethodDescriptor; + + private ServiceDescriptor descriptor; + private Map methodDescriptors; + private IRubyObject name; +} diff --git a/ruby/src/main/java/google/ProtobufJavaService.java b/ruby/src/main/java/google/ProtobufJavaService.java index 00d60a1498..c9b7c4e522 100644 --- a/ruby/src/main/java/google/ProtobufJavaService.java +++ b/ruby/src/main/java/google/ProtobufJavaService.java @@ -55,6 +55,8 @@ public class ProtobufJavaService implements BasicLibraryService { RubyMap.createRubyMap(ruby); RubyOneofDescriptor.createRubyOneofDescriptor(ruby); RubyDescriptor.createRubyDescriptor(ruby); + RubyMethodDescriptor.createRubyMethodDescriptor(ruby); + RubyServiceDescriptor.createRubyServiceDescriptor(ruby); RubyDescriptorPool.createRubyDescriptorPool(ruby); return true; } diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb index e6cd08b273..a45e6006af 100755 --- a/ruby/tests/basic.rb +++ b/ruby/tests/basic.rb @@ -3,6 +3,7 @@ # basic_test_pb.rb is in the same directory as this test. $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) +require 'basic_test_features_pb' require 'basic_test_pb' require 'common_tests' require 'google/protobuf' @@ -722,31 +723,110 @@ module BasicTest message.repeated_msg[0].foo = "bar" end end - end - def test_oneof_fields_respond_to? # regression test for issue 9202 - msg = proto_module::OneofMessage.new - # `has_` prefix + "?" suffix actions should work for oneofs fields and members. - assert msg.has_my_oneof? - assert msg.respond_to? :has_my_oneof? - assert_respond_to msg, :has_a? - refute msg.has_a? - assert_respond_to msg, :has_b? - refute msg.has_b? - assert_respond_to msg, :has_c? - refute msg.has_c? - assert_respond_to msg, :has_d? - refute msg.has_d? - end + def test_oneof_fields_respond_to? # regression test for issue 9202 + msg = proto_module::OneofMessage.new + # `has_` prefix + "?" suffix actions should work for oneofs fields and members. + assert_false msg.has_my_oneof? + assert msg.respond_to? :has_my_oneof? + assert_respond_to msg, :has_a? + refute msg.has_a? + assert_respond_to msg, :has_b? + refute msg.has_b? + assert_respond_to msg, :has_c? + refute msg.has_c? + assert_respond_to msg, :has_d? + refute msg.has_d? + end + + def test_string_subclass + str = "hello" + myString = Class.new(String) + + m = proto_module::TestMessage.new( + optional_string: myString.new(str), + ) + + assert_equal str, m.optional_string + end + + def test_proto3_explicit_presence + descriptor = TestMessage.descriptor.lookup("optional_int32") + assert_true descriptor.has_presence? + assert_false descriptor.options.has_features? + end + + def test_proto3_implicit_presence + descriptor = TestSingularFields.descriptor.lookup("singular_int32") + assert_false descriptor.has_presence? + assert_false descriptor.options.has_features? + end + + def test_proto3_packed_encoding + descriptor = TestMessage.descriptor.lookup("repeated_int32") + assert_true descriptor.is_packed? + assert_false descriptor.options.has_features? + end + + def test_proto3_expanded_encoding + descriptor = TestUnpackedMessage.descriptor.lookup("repeated_int32") + assert_false descriptor.is_packed? + assert_false descriptor.options.has_features? + end - def test_string_subclass - str = "hello" - myString = Class.new(String) + def test_proto3_expanded_encoding_unpackable + descriptor = TestMessage.descriptor.lookup("optional_msg") + assert_false descriptor.is_packed? + assert_false descriptor.options.has_features? + end - m = proto_module::TestMessage.new( - optional_string: myString.new(str), - ) + def test_editions_explicit_presence + descriptor = TestFeaturesMessage.descriptor.lookup("explicit") + assert_true descriptor.has_presence? + assert_false descriptor.options.has_features? + end + + def test_editions_implicit_presence + descriptor = TestFeaturesMessage.descriptor.lookup("implicit") + assert_false descriptor.has_presence? + assert_false descriptor.options.has_features? + end + + def test_editions_required_presence + descriptor = TestFeaturesMessage.descriptor.lookup("legacy_required") + assert_equal :required, descriptor.label + assert_false descriptor.options.has_features? + end + + def test_editions_packed_encoding + descriptor = TestFeaturesMessage.descriptor.lookup("packed") + assert_true descriptor.is_packed? + assert_false descriptor.options.has_features? + end + + def test_editions_expanded_encoding + descriptor = TestFeaturesMessage.descriptor.lookup("expanded") + assert_false descriptor.is_packed? + assert_false descriptor.options.has_features? + end + + def test_editions_expanded_encoding_unpackable + descriptor = TestFeaturesMessage.descriptor.lookup("unpackable") + assert_false descriptor.is_packed? + assert_false descriptor.options.has_features? + end + + def test_field_delimited_encoding + descriptor = TestFeaturesMessage.descriptor.lookup("delimited") + assert_equal :group, descriptor.type + assert_false descriptor.options.has_features? + end + + def test_field_length_prefixed_encoding + descriptor = TestFeaturesMessage.descriptor.lookup("length_prefixed") + assert_equal :message, descriptor.type + assert_false descriptor.options.has_features? + end - assert_equal str, m.optional_string end end diff --git a/ruby/tests/basic_proto2.rb b/ruby/tests/basic_proto2.rb index e9fce5751d..2112732664 100755 --- a/ruby/tests/basic_proto2.rb +++ b/ruby/tests/basic_proto2.rb @@ -6,6 +6,7 @@ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) require 'basic_test_proto2_pb' require 'common_tests' require 'google/protobuf' +require 'google/protobuf/descriptor_pb' require 'json' require 'test/unit' @@ -347,5 +348,35 @@ module BasicTestProto2 decoded_message = TestMessageSet.decode encoded_message assert_equal message, decoded_message end + + def test_field_explicit_presence + descriptor = TestMessage.descriptor.lookup("optional_int32") + assert_true descriptor.has_presence? + assert_false descriptor.options.has_features? + end + + def test_field_expanded_encoding + descriptor = TestMessage.descriptor.lookup("repeated_int32") + assert_false descriptor.is_packed? + assert_false descriptor.options.has_features? + end + + def test_field_packed_encoding + descriptor = TestPackedMessage.descriptor.lookup("repeated_int32") + assert_true descriptor.is_packed? + assert_false descriptor.options.has_features? + end + + def test_field_group_type + descriptor = TestGroupMessage.descriptor.lookup("groupfield") + assert_equal :group, descriptor.type + assert_false descriptor.options.has_features? + end + + def test_field_required + descriptor = TestRequiredMessage.descriptor.lookup("required_int32") + assert_equal :required, descriptor.label + assert_false descriptor.options.has_features? + end end end diff --git a/ruby/tests/basic_test.proto b/ruby/tests/basic_test.proto index 5c9bb6012e..2479fa5a8a 100644 --- a/ruby/tests/basic_test.proto +++ b/ruby/tests/basic_test.proto @@ -53,6 +53,10 @@ message TestMessage { optional TestSingularFields optional_msg2 = 23; } +message TestUnpackedMessage { + repeated int32 repeated_int32 = 25 [packed = false]; +} + message TestSingularFields { int32 singular_int32 = 1; int64 singular_int64 = 2; diff --git a/ruby/tests/basic_test_features.proto b/ruby/tests/basic_test_features.proto new file mode 100644 index 0000000000..70e9a5bc3e --- /dev/null +++ b/ruby/tests/basic_test_features.proto @@ -0,0 +1,21 @@ +edition = "2023"; + +package basic_test; + +import "test_import_proto2.proto"; + +option features.enum_type = CLOSED; // Ignored by ruby. +option features.field_presence = IMPLICIT; + +message TestFeaturesMessage { + int32 implicit = 1; + int32 explicit = 2 [features.field_presence = EXPLICIT]; + int32 legacy_required = 3 [features.field_presence = LEGACY_REQUIRED]; + + repeated int32 packed = 50; + repeated int32 expanded = 51 [features.repeated_field_encoding = EXPANDED]; + repeated foo_bar.proto2.TestImportedMessage unpackable = 52; + + TestFeaturesMessage delimited = 100 [features.message_encoding = DELIMITED]; + TestFeaturesMessage length_prefixed = 101; +} diff --git a/ruby/tests/basic_test_proto2.proto b/ruby/tests/basic_test_proto2.proto index 85d61cf6b1..bc20418ba8 100644 --- a/ruby/tests/basic_test_proto2.proto +++ b/ruby/tests/basic_test_proto2.proto @@ -46,6 +46,20 @@ message TestMessage { repeated TestEnum repeated_enum = 22; } +message TestPackedMessage { + repeated int32 repeated_int32 = 12 [packed = true]; +} + +message TestGroupMessage { + optional group GroupField = 1 { + optional int32 a = 1; + } +} + +message TestRequiredMessage { + required int32 required_int32 = 1; +} + message TestMessage2 { optional int32 foo = 1; } diff --git a/ruby/tests/generated_code_editions.proto b/ruby/tests/generated_code_editions.proto new file mode 100644 index 0000000000..fc5eb04cca --- /dev/null +++ b/ruby/tests/generated_code_editions.proto @@ -0,0 +1,96 @@ +edition = "2023"; + +package a.b.editions; + +option features.repeated_field_encoding = EXPANDED; +option features.utf8_validation = NONE; + +message TestMessage { + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + bool optional_bool = 5; + double optional_double = 6; + float optional_float = 7; + string optional_string = 8; + bytes optional_bytes = 9; + TestEnum optional_enum = 10; + TestMessage optional_msg = 11; + repeated int32 repeated_int32 = 21; + repeated int64 repeated_int64 = 22; + repeated uint32 repeated_uint32 = 23; + repeated uint64 repeated_uint64 = 24; + repeated bool repeated_bool = 25; + repeated double repeated_double = 26; + repeated float repeated_float = 27; + repeated string repeated_string = 28; + repeated bytes repeated_bytes = 29; + repeated TestEnum repeated_enum = 30; + repeated TestMessage repeated_msg = 31; + int32 required_int32 = 41 [features.field_presence = LEGACY_REQUIRED]; + + int64 required_int64 = 42 [features.field_presence = LEGACY_REQUIRED]; + + uint32 required_uint32 = 43 [features.field_presence = LEGACY_REQUIRED]; + + uint64 required_uint64 = 44 [features.field_presence = LEGACY_REQUIRED]; + + bool required_bool = 45 [features.field_presence = LEGACY_REQUIRED]; + + double required_double = 46 [features.field_presence = LEGACY_REQUIRED]; + + float required_float = 47 [features.field_presence = LEGACY_REQUIRED]; + + string required_string = 48 [features.field_presence = LEGACY_REQUIRED]; + + bytes required_bytes = 49 [features.field_presence = LEGACY_REQUIRED]; + + TestEnum required_enum = 50 [features.field_presence = LEGACY_REQUIRED]; + + TestMessage required_msg = 51 [features.field_presence = LEGACY_REQUIRED]; + + oneof my_oneof { + int32 oneof_int32 = 61; + int64 oneof_int64 = 62; + uint32 oneof_uint32 = 63; + uint64 oneof_uint64 = 64; + bool oneof_bool = 65; + double oneof_double = 66; + float oneof_float = 67; + string oneof_string = 68; + bytes oneof_bytes = 69; + TestEnum oneof_enum = 70; + TestMessage oneof_msg = 71; + } + + message NestedMessage { + int32 foo = 1; + } + + NestedMessage nested_message = 80; + + // Reserved for non-existing field test. + // int32 non_exist = 89; +} + +enum TestEnum { + option features.enum_type = CLOSED; + + Default = 0; + A = 1; + B = 2; + C = 3; + v0 = 4; +} + +message TestUnknown { + TestUnknown optional_unknown = 11; + repeated TestUnknown repeated_unknown = 31; + + oneof my_oneof { + TestUnknown oneof_unknown = 51; + } + + int32 unknown_field = 89; +} diff --git a/ruby/tests/generated_code_test.rb b/ruby/tests/generated_code_test.rb index aed1cf8ebc..b2092c6e1a 100755 --- a/ruby/tests/generated_code_test.rb +++ b/ruby/tests/generated_code_test.rb @@ -3,6 +3,7 @@ # generated_code.rb is in the same directory as this test. $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) +require 'generated_code_editions_pb' require 'generated_code_pb' require 'test_import_pb' require 'test_ruby_package_pb' @@ -19,5 +20,7 @@ class GeneratedCodeTest < Test::Unit::TestCase A::B::C::TestLowercaseNested::Lowercase.new FooBar::TestImportedMessage.new A::B::TestRubyPackageMessage.new + A::B::Editions::TestMessage.new + A::B::Editions::TestMessage::NestedMessage.new end end diff --git a/ruby/tests/repeated_field_test.rb b/ruby/tests/repeated_field_test.rb index 41f90b4932..49c7045a99 100755 --- a/ruby/tests/repeated_field_test.rb +++ b/ruby/tests/repeated_field_test.rb @@ -37,7 +37,6 @@ class RepeatedFieldTest < Test::Unit::TestCase repeated_field_names(TestMessage).each do |field_name| assert_nil m.send(field_name).first assert_empty m.send(field_name).first(0) - assert_empty m.send(field_name).first(1) end fill_test_msg(m) diff --git a/ruby/tests/service_test.proto b/ruby/tests/service_test.proto new file mode 100644 index 0000000000..dc131fea0a --- /dev/null +++ b/ruby/tests/service_test.proto @@ -0,0 +1,52 @@ +syntax = "proto3"; + +package service_test_protos; + +import "google/protobuf/descriptor.proto"; + +message UnaryRequestType { + string ping = 1; +} + +message UnaryResponseType { + string pong = 1; +} + +message StreamRequestType { + string ping = 1; + uint32 sequence = 2; +} + +message StreamResponseType { + string pong = 1; + uint32 sequence = 2; +} + +message TestOptionsType { + uint32 int_option_value = 1; +} + +extend google.protobuf.ServiceOptions { + optional TestOptionsType test_options = 50000; +} + +service TestService { + option (test_options).int_option_value = 8325; + + rpc UnaryOne(UnaryRequestType) returns (UnaryResponseType); + rpc UnaryTwo(UnaryRequestType) returns (UnaryResponseType); + + rpc IdempotentMethod(UnaryRequestType) returns (UnaryResponseType) { + option idempotency_level = IDEMPOTENT; + } + rpc PureMethod(UnaryRequestType) returns (UnaryResponseType) { + option idempotency_level = NO_SIDE_EFFECTS; + } + + rpc StreamingMethod(stream StreamRequestType) + returns (stream StreamResponseType); +} + +service DeprecatedService { + option deprecated = true; +} diff --git a/ruby/tests/service_test.rb b/ruby/tests/service_test.rb new file mode 100644 index 0000000000..729b799599 --- /dev/null +++ b/ruby/tests/service_test.rb @@ -0,0 +1,61 @@ +#!/usr/bin/ruby + +require 'google/protobuf' +require 'service_test_pb' +require 'test/unit' +require 'json' + +class ServiceTest < Test::Unit::TestCase + def setup + @test_service = Google::Protobuf::DescriptorPool.generated_pool.lookup('service_test_protos.TestService') + @deprecated_service = Google::Protobuf::DescriptorPool.generated_pool.lookup('service_test_protos.DeprecatedService') + @test_service_methods = @test_service.to_h { |method| [method.name, method] } + end + + def test_lookup_service_descriptor + assert_kind_of Google::Protobuf::ServiceDescriptor, @test_service + assert_equal 'service_test_protos.TestService', @test_service.name + end + + def test_file_descriptor + assert_kind_of Google::Protobuf::FileDescriptor, @test_service.file_descriptor + assert_equal 'service_test.proto', @test_service.file_descriptor.name + end + + def test_method_iteration + @test_service.each { |method| assert_kind_of Google::Protobuf::MethodDescriptor, method } + assert_equal %w(UnaryOne UnaryTwo), @test_service.map { |method| method.name }.first(2) + end + + def test_service_options + assert @deprecated_service.options.deprecated + refute @test_service.options.deprecated + end + + def test_service_options_extensions + extension_field = Google::Protobuf::DescriptorPool.generated_pool.lookup('service_test_protos.test_options') + assert_equal 8325, extension_field.get(@test_service.options).int_option_value + end + + def test_method_options + assert_equal :IDEMPOTENT, @test_service_methods['IdempotentMethod'].options.idempotency_level + assert_equal :NO_SIDE_EFFECTS, @test_service_methods['PureMethod'].options.idempotency_level + end + + def test_method_input_type + unary_request_type = Google::Protobuf::DescriptorPool.generated_pool.lookup('service_test_protos.UnaryRequestType') + assert_same unary_request_type, @test_service_methods['UnaryOne'].input_type + end + + def test_method_output_type + unary_response_type = Google::Protobuf::DescriptorPool.generated_pool.lookup('service_test_protos.UnaryResponseType') + assert_same unary_response_type, @test_service_methods['UnaryOne'].output_type + end + + def test_method_streaming_flags + refute @test_service_methods['UnaryOne'].client_streaming + refute @test_service_methods['UnaryOne'].server_streaming + assert @test_service_methods['StreamingMethod'].client_streaming + assert @test_service_methods['StreamingMethod'].server_streaming + end +end diff --git a/rust/cpp.rs b/rust/cpp.rs index 5225564af1..abb24d7fdc 100644 --- a/rust/cpp.rs +++ b/rust/cpp.rs @@ -727,7 +727,6 @@ impl_ProxiedInMapValue_for_key_types!( mod tests { use super::*; use googletest::prelude::*; - use std::boxed::Box; // We need to allocate the byte array so SerializedData can own it and // deallocate it in its drop. This function makes it easier to do so for our diff --git a/rust/cpp_kernel/cpp_api.h b/rust/cpp_kernel/cpp_api.h index 409d169b31..3d82472d54 100644 --- a/rust/cpp_kernel/cpp_api.h +++ b/rust/cpp_kernel/cpp_api.h @@ -86,6 +86,9 @@ struct PtrAndLen { bool __rust_proto_thunk__Map_##rust_key_ty##_##rust_value_ty##_insert( \ google::protobuf::Map* m, ffi_key_ty key, ffi_value_ty value) { \ auto iter_and_inserted = m->try_emplace(to_cpp_key, to_cpp_value); \ + if (!iter_and_inserted.second) { \ + iter_and_inserted.first->second = to_cpp_value; \ + } \ return iter_and_inserted.second; \ } \ bool __rust_proto_thunk__Map_##rust_key_ty##_##rust_value_ty##_get( \ diff --git a/rust/map.rs b/rust/map.rs index 53be666973..4d80d1ea78 100644 --- a/rust/map.rs +++ b/rust/map.rs @@ -314,8 +314,18 @@ where V::map_get(self.as_view(), key.into()) } - pub fn copy_from(&mut self, _src: MapView<'_, K, V>) { - todo!("implement b/28530933"); + pub fn copy_from<'a, 'b>( + &mut self, + src: impl IntoIterator>, impl Into>)>, + ) where + K: 'a, + V: 'b, + { + //TODO + self.clear(); + for (k, v) in src.into_iter() { + self.insert(k, v); + } } /// Returns an iterator visiting all key-value pairs in arbitrary order. @@ -432,6 +442,20 @@ where } } +impl<'msg, 'k, 'v, KView, VView, K, V> Extend<(KView, VView)> for MapMut<'msg, K, V> +where + K: Proxied + ?Sized + 'msg + 'k, + V: ProxiedInMapValue + ?Sized + 'msg + 'v, + KView: Into>, + VView: Into>, +{ + fn extend>(&mut self, iter: T) { + for (k, v) in iter.into_iter() { + self.insert(k, v); + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -528,6 +552,84 @@ mod tests { ); } + #[test] + fn test_overwrite_insert() { + let mut map: Map = Map::new(); + let mut map_mut = map.as_mut(); + assert!(map_mut.insert(0, "fizz")); + // insert should return false when the key is already present + assert!(!map_mut.insert(0, "buzz")); + + assert_that!( + map.as_mut().iter().collect::>(), + unordered_elements_are![eq((0, ProtoStr::from_str("buzz"))),] + ); + } + + #[test] + fn test_extend() { + let mut map: Map = Map::new(); + let mut map_mut = map.as_mut(); + map_mut.extend([(0, "fizz"), (1, "buzz"), (2, "fizzbuzz")]); + + assert_that!( + map.as_view().into_iter().collect::>(), + unordered_elements_are![ + eq((0, ProtoStr::from_str("fizz"))), + eq((1, ProtoStr::from_str("buzz"))), + eq((2, ProtoStr::from_str("fizzbuzz"))) + ] + ); + + let mut map_2: Map = Map::new(); + let mut map_2_mut = map_2.as_mut(); + map_2_mut.extend([(2, "bing"), (3, "bong")]); + + let mut map_mut = map.as_mut(); + map_mut.extend(&map_2); + + assert_that!( + map.as_view().into_iter().collect::>(), + unordered_elements_are![ + eq((0, ProtoStr::from_str("fizz"))), + eq((1, ProtoStr::from_str("buzz"))), + eq((2, ProtoStr::from_str("bing"))), + eq((3, ProtoStr::from_str("bong"))) + ] + ); + } + + #[test] + fn test_copy_from() { + let mut map: Map = Map::new(); + let mut map_mut = map.as_mut(); + map_mut.copy_from([(0, "fizz"), (1, "buzz"), (2, "fizzbuzz")]); + + assert_that!( + map.as_view().into_iter().collect::>(), + unordered_elements_are![ + eq((0, ProtoStr::from_str("fizz"))), + eq((1, ProtoStr::from_str("buzz"))), + eq((2, ProtoStr::from_str("fizzbuzz"))) + ] + ); + + let mut map_2: Map = Map::new(); + let mut map_2_mut = map_2.as_mut(); + map_2_mut.copy_from([(2, "bing"), (3, "bong")]); + + let mut map_mut = map.as_mut(); + map_mut.copy_from(&map_2); + + assert_that!( + map.as_view().into_iter().collect::>(), + unordered_elements_are![ + eq((2, ProtoStr::from_str("bing"))), + eq((3, ProtoStr::from_str("bong"))) + ] + ); + } + #[test] fn test_all_maps_can_be_constructed() { macro_rules! gen_proto_values { diff --git a/rust/proxied.rs b/rust/proxied.rs index 3d1031528e..8d9214d28e 100644 --- a/rust/proxied.rs +++ b/rust/proxied.rs @@ -48,7 +48,6 @@ use crate::RepeatedMut; use crate::__internal::Private; use crate::repeated::ProxiedInRepeated; use std::fmt::Debug; -use std::marker::{Send, Sync}; /// A type that can be accessed through a reference-like proxy. /// @@ -171,7 +170,7 @@ pub trait MutProxy<'msg>: ViewProxy<'msg> { /// example: /// /// ```ignore - /// let mut sub: Mut = msg.submsg_mut().or_default(); + /// let mut sub: Mut = msg.submsg_mut(); /// sub.as_mut().field_x_mut().set(10); // field_x_mut is fn(self) /// sub.field_y_mut().set(20); // `sub` is now consumed /// ``` diff --git a/rust/test/cpp/debug_test.rs b/rust/test/cpp/debug_test.rs index d6feec36bc..eb9237ee72 100644 --- a/rust/test/cpp/debug_test.rs +++ b/rust/test/cpp/debug_test.rs @@ -5,7 +5,7 @@ use googletest::prelude::*; fn test_debug() { let mut msg = DebugMsg::new(); msg.set_id(1); - msg.secret_user_data_mut().set("password"); + msg.set_secret_user_data("password"); assert_that!(format!("{msg:?}"), contains_substring("id: 1")); assert_that!(format!("{msg:?}"), not(contains_substring("password"))); diff --git a/rust/test/cpp/interop/BUILD b/rust/test/cpp/interop/BUILD index 6db733a44c..229f7334ab 100644 --- a/rust/test/cpp/interop/BUILD +++ b/rust/test/cpp/interop/BUILD @@ -15,10 +15,6 @@ cc_library( rust_test( name = "interop_test", srcs = ["main.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ ":test_utils", "//rust:protobuf_cpp", diff --git a/rust/test/reserved.proto b/rust/test/reserved.proto index 9a80926ee9..1f8c2a937d 100644 --- a/rust/test/reserved.proto +++ b/rust/test/reserved.proto @@ -23,14 +23,16 @@ message Self { optional string false = 4; } -message pub { +message Pub { enum Self { enum = 0; } } -message enum { +message enum {} + +message Ref { oneof self { - .type.type.pub.Self const = 3; + .type.type.Pub.Self const = 3; } } diff --git a/rust/test/shared/BUILD b/rust/test/shared/BUILD index f62ba1e2d0..275da75035 100644 --- a/rust/test/shared/BUILD +++ b/rust/test/shared/BUILD @@ -43,10 +43,6 @@ rust_library( rust_test( name = "child_parent_upb_test", srcs = ["child_parent_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust/test:child_upb_rust_proto", "//rust/test:parent_upb_rust_proto", @@ -57,10 +53,6 @@ rust_test( rust_test( name = "child_parent_cpp_test", srcs = ["child_parent_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust/test:child_cc_rust_proto", "//rust/test:parent_cc_rust_proto", @@ -71,10 +63,6 @@ rust_test( rust_test( name = "edition2023_cpp_test", srcs = ["edition2023_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust/test:edition2023_cc_rust_proto", "@crate_index//:googletest", @@ -84,10 +72,6 @@ rust_test( rust_test( name = "edition2023_upb_test", srcs = ["edition2023_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust/test:edition2023_upb_rust_proto", "@crate_index//:googletest", @@ -100,10 +84,6 @@ rust_test( aliases = { "//rust:protobuf_cpp": "protobuf", }, - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust:protobuf_cpp", "//rust/test:enums_cc_rust_proto", @@ -118,10 +98,6 @@ rust_test( aliases = { "//rust:protobuf_upb": "protobuf", }, - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust:protobuf_upb", "//rust/test:enums_upb_rust_proto", @@ -133,10 +109,6 @@ rust_test( rust_test( name = "import_public_cpp_test", srcs = ["import_public_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust/test:import_public_cc_rust_proto", ], @@ -145,10 +117,6 @@ rust_test( rust_test( name = "import_public_upb_test", srcs = ["import_public_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust/test:import_public_upb_rust_proto", ], @@ -157,10 +125,6 @@ rust_test( rust_test( name = "package_cpp_test", srcs = ["package_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust/test:dots_in_package_cc_rust_proto", "//rust/test:no_package_cc_rust_proto", @@ -171,10 +135,6 @@ rust_test( rust_test( name = "package_upb_test", srcs = ["package_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust/test:dots_in_package_upb_rust_proto", "//rust/test:no_package_upb_rust_proto", @@ -185,30 +145,18 @@ rust_test( rust_test( name = "package_disambiguation_cpp_test", srcs = ["package_disambiguation_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = ["//rust/test:package_disabiguation_cc_rust_proto"], ) rust_test( name = "package_disambiguation_upb_test", srcs = ["package_disambiguation_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = ["//rust/test:package_disabiguation_upb_rust_proto"], ) rust_test( name = "reserved_cpp_test", srcs = ["reserved_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust/test:reserved_cc_rust_proto", "//rust/test:unittest_cc_rust_proto", @@ -219,10 +167,6 @@ rust_test( rust_test( name = "reserved_upb_test", srcs = ["reserved_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust/test:reserved_upb_rust_proto", "//rust/test:unittest_upb_rust_proto", @@ -233,20 +177,12 @@ rust_test( rust_test( name = "nested_types_cpp_test", srcs = ["nested_types_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = ["//rust/test:unittest_cc_rust_proto"], ) rust_test( name = "nested_types_upb_test", srcs = ["nested_types_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = ["//rust/test:unittest_upb_rust_proto"], ) @@ -260,10 +196,6 @@ rust_test( proc_macro_deps = [ "@crate_index//:paste", ], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust:protobuf_cpp", "//rust/test:unittest_cc_rust_proto", @@ -282,10 +214,6 @@ rust_test( proc_macro_deps = [ "@crate_index//:paste", ], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust:protobuf_upb", "//rust/test:unittest_upb_rust_proto", @@ -301,10 +229,6 @@ rust_test( "//rust:protobuf_cpp": "protobuf", "//rust/test/shared:matchers_cpp": "matchers", }, - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust:protobuf_cpp", "//rust/test:unittest_proto3_cc_rust_proto", @@ -321,10 +245,6 @@ rust_test( "//rust:protobuf_upb": "protobuf", "//rust/test/shared:matchers_upb": "matchers", }, - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust:protobuf_upb", "//rust/test:unittest_proto3_optional_upb_rust_proto", @@ -337,10 +257,6 @@ rust_test( rust_test( name = "serialization_upb_test", srcs = ["serialization_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust/test:unittest_upb_rust_proto", "@crate_index//:googletest", @@ -350,10 +266,6 @@ rust_test( rust_test( name = "serialization_cpp_test", srcs = ["serialization_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust/test:unittest_cc_rust_proto", "@crate_index//:googletest", @@ -366,10 +278,6 @@ rust_test( aliases = { "//rust:protobuf_cpp": "protobuf", }, - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust:protobuf_cpp", "//rust/test:nested_cc_rust_proto", @@ -383,10 +291,6 @@ rust_test( aliases = { "//rust:protobuf_upb": "protobuf", }, - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust:protobuf_upb", "//rust/test:nested_upb_rust_proto", @@ -403,10 +307,6 @@ rust_test( proc_macro_deps = [ "@crate_index//:paste", ], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust:protobuf_cpp", "//rust/test:unittest_cc_rust_proto", @@ -423,10 +323,6 @@ rust_test( proc_macro_deps = [ "@crate_index//:paste", ], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust:protobuf_upb", "//rust/test:unittest_upb_rust_proto", @@ -440,10 +336,6 @@ rust_test( proc_macro_deps = [ "@crate_index//:paste", ], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust/test:map_unittest_cc_rust_proto", "//rust/test:unittest_cc_rust_proto", @@ -457,10 +349,6 @@ rust_test( proc_macro_deps = [ "@crate_index//:paste", ], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust/test:map_unittest_upb_rust_proto", "//rust/test:unittest_upb_rust_proto", @@ -471,10 +359,6 @@ rust_test( rust_test( name = "reserved_crate_name_cc_test", srcs = ["reserved_crate_name_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust/test:struct_cc_rust_proto", ], @@ -483,10 +367,6 @@ rust_test( rust_test( name = "reserved_crate_name_upb_test", srcs = ["reserved_crate_name_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust/test:struct_upb_rust_proto", ], @@ -495,10 +375,6 @@ rust_test( rust_test( name = "fields_with_imported_types_cpp_test", srcs = ["fields_with_imported_types_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust:protobuf_cpp", "//rust/test:fields_with_imported_types_cc_rust_proto", @@ -510,10 +386,6 @@ rust_test( rust_test( name = "fields_with_imported_types_upb_test", srcs = ["fields_with_imported_types_test.rs"], - tags = [ - # TODO: Enable testing on arm once we support sanitizers for Rust on Arm. - "not_build:arm", - ], deps = [ "//rust:protobuf_upb", "//rust/test:fields_with_imported_types_upb_rust_proto", diff --git a/rust/test/shared/accessors_map_test.rs b/rust/test/shared/accessors_map_test.rs index 930b1e5fe7..be22aebf69 100644 --- a/rust/test/shared/accessors_map_test.rs +++ b/rust/test/shared/accessors_map_test.rs @@ -167,7 +167,7 @@ macro_rules! generate_map_with_msg_values_tests { // this block makes sure `insert` copies/moves, not borrows. { let mut msg_val = TestAllTypes::new(); - msg_val.optional_int32_mut().set(1001); + msg_val.set_optional_int32(1001); assert_that!( msg .[< map_ $k_field _all_types_mut >]() diff --git a/rust/test/shared/accessors_proto3_test.rs b/rust/test/shared/accessors_proto3_test.rs index 3ab69d4157..57356fa9ce 100644 --- a/rust/test/shared/accessors_proto3_test.rs +++ b/rust/test/shared/accessors_proto3_test.rs @@ -8,47 +8,35 @@ /// Tests covering accessors for singular bool, int32, int64, and bytes fields /// on proto3. use googletest::prelude::*; -use matchers::{is_set, is_unset}; use protobuf::Optional; -use unittest_proto3::{TestAllTypes, TestAllTypes_}; -use unittest_proto3_optional::{TestProto3Optional, TestProto3Optional_}; +use unittest_proto3::{test_all_types, TestAllTypes}; +use unittest_proto3_optional::{test_proto3_optional, TestProto3Optional}; #[test] fn test_fixed32_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_fixed32(), eq(0)); - assert_that!(msg.optional_fixed32_mut().get(), eq(0)); msg.set_optional_fixed32(42); - assert_that!(msg.optional_fixed32_mut().get(), eq(42)); assert_that!(msg.optional_fixed32(), eq(42)); msg.set_optional_fixed32(u32::default()); assert_that!(msg.optional_fixed32(), eq(0)); - assert_that!(msg.optional_fixed32_mut().get(), eq(0)); - msg.optional_fixed32_mut().set(43); + msg.set_optional_fixed32(43); assert_that!(msg.optional_fixed32(), eq(43)); - assert_that!(msg.optional_fixed32_mut().get(), eq(43)); } #[test] fn test_bool_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_bool(), eq(false)); - assert_that!(msg.optional_bool_mut().get(), eq(false)); msg.set_optional_bool(true); assert_that!(msg.optional_bool(), eq(true)); - assert_that!(msg.optional_bool_mut().get(), eq(true)); msg.set_optional_bool(bool::default()); assert_that!(msg.optional_bool(), eq(false)); - assert_that!(msg.optional_bool_mut().get(), eq(false)); - - msg.optional_bool_mut().set(true); - assert_that!(msg.optional_bool(), eq(true)); - assert_that!(msg.optional_bool_mut().get(), eq(true)); } #[test] @@ -57,26 +45,18 @@ fn test_bytes_accessors() { // Note: even though it's named 'optional_bytes', the field is actually not // proto3 optional, so it does not support presence. assert_that!(*msg.optional_bytes(), empty()); - assert_that!(*msg.optional_bytes_mut().get(), empty()); msg.set_optional_bytes(b"accessors_test"); assert_that!(msg.optional_bytes(), eq(b"accessors_test")); - assert_that!(msg.optional_bytes_mut().get(), eq(b"accessors_test")); { let s = Vec::from(&b"hello world"[..]); msg.set_optional_bytes(&s[..]); } assert_that!(msg.optional_bytes(), eq(b"hello world")); - assert_that!(msg.optional_bytes_mut().get(), eq(b"hello world")); - - msg.optional_bytes_mut().clear(); - assert_that!(*msg.optional_bytes(), empty()); - assert_that!(*msg.optional_bytes_mut().get(), empty()); msg.set_optional_bytes(b""); assert_that!(*msg.optional_bytes(), empty()); - assert_that!(*msg.optional_bytes_mut().get(), empty()); } #[test] @@ -84,8 +64,6 @@ fn test_optional_bytes_accessors() { let mut msg = TestProto3Optional::new(); assert_that!(*msg.optional_bytes(), empty()); assert_that!(msg.optional_bytes_opt(), eq(Optional::Unset(&b""[..]))); - assert_that!(*msg.optional_bytes_mut().get(), empty()); - assert_that!(msg.optional_bytes_mut(), is_unset()); { let s = Vec::from(&b"hello world"[..]); @@ -93,36 +71,14 @@ fn test_optional_bytes_accessors() { } assert_that!(msg.optional_bytes(), eq(b"hello world")); assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b"hello world"[..]))); - assert_that!(msg.optional_bytes_mut(), is_set()); - assert_that!(msg.optional_bytes_mut().get(), eq(b"hello world")); - - msg.optional_bytes_mut().or_default().set(b"accessors_test"); - assert_that!(msg.optional_bytes(), eq(b"accessors_test")); - assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b"accessors_test"[..]))); - assert_that!(msg.optional_bytes_mut(), is_set()); - assert_that!(msg.optional_bytes_mut().get(), eq(b"accessors_test")); - assert_that!(msg.optional_bytes_mut().or_default().get(), eq(b"accessors_test")); - - msg.optional_bytes_mut().clear(); - assert_that!(*msg.optional_bytes(), empty()); - assert_that!(msg.optional_bytes_opt(), eq(Optional::Unset(&b""[..]))); - assert_that!(msg.optional_bytes_mut(), is_unset()); msg.set_optional_bytes(b""); assert_that!(*msg.optional_bytes(), empty()); assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b""[..]))); - msg.optional_bytes_mut().clear(); - msg.optional_bytes_mut().or_default(); - assert_that!(*msg.optional_bytes(), empty()); - assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b""[..]))); - - msg.optional_bytes_mut().or_default().set(b"\xffbinary\x85non-utf8"); + msg.set_optional_bytes(b"\xffbinary\x85non-utf8"); assert_that!(msg.optional_bytes(), eq(b"\xffbinary\x85non-utf8")); assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b"\xffbinary\x85non-utf8"[..]))); - assert_that!(msg.optional_bytes_mut(), is_set()); - assert_that!(msg.optional_bytes_mut().get(), eq(b"\xffbinary\x85non-utf8")); - assert_that!(msg.optional_bytes_mut().or_default().get(), eq(b"\xffbinary\x85non-utf8")); } #[test] @@ -131,26 +87,18 @@ fn test_string_accessors() { // Note: even though it's named 'optional_string', the field is actually not // proto3 optional, so it does not support presence. assert_that!(*msg.optional_string().as_bytes(), empty()); - assert_that!(*msg.optional_string_mut().get().as_bytes(), empty()); msg.set_optional_string("accessors_test"); assert_that!(msg.optional_string(), eq("accessors_test")); - assert_that!(msg.optional_string_mut().get(), eq("accessors_test")); { let s = String::from("hello world"); msg.set_optional_string(&s[..]); } assert_that!(msg.optional_string(), eq("hello world")); - assert_that!(msg.optional_string_mut().get(), eq("hello world")); - - msg.optional_string_mut().clear(); - assert_that!(*msg.optional_string().as_bytes(), empty()); - assert_that!(*msg.optional_string_mut().get().as_bytes(), empty()); msg.set_optional_string(""); assert_that!(*msg.optional_string().as_bytes(), empty()); - assert_that!(*msg.optional_string_mut().get().as_bytes(), empty()); } #[test] @@ -158,8 +106,6 @@ fn test_optional_string_accessors() { let mut msg = TestProto3Optional::new(); assert_that!(*msg.optional_string().as_bytes(), empty()); assert_that!(msg.optional_string_opt(), eq(Optional::Unset("".into()))); - assert_that!(*msg.optional_string_mut().get().as_bytes(), empty()); - assert_that!(msg.optional_string_mut(), is_unset()); { let s = String::from("hello world"); @@ -167,78 +113,45 @@ fn test_optional_string_accessors() { } assert_that!(msg.optional_string(), eq("hello world")); assert_that!(msg.optional_string_opt(), eq(Optional::Set("hello world".into()))); - assert_that!(msg.optional_string_mut(), is_set()); - assert_that!(msg.optional_string_mut().get(), eq("hello world")); - msg.optional_string_mut().or_default().set("accessors_test"); + msg.set_optional_string("accessors_test"); assert_that!(msg.optional_string(), eq("accessors_test")); assert_that!(msg.optional_string_opt(), eq(Optional::Set("accessors_test".into()))); - assert_that!(msg.optional_string_mut(), is_set()); - assert_that!(msg.optional_string_mut().get(), eq("accessors_test")); - assert_that!(msg.optional_string_mut().or_default().get(), eq("accessors_test")); - - msg.optional_string_mut().clear(); - assert_that!(*msg.optional_string().as_bytes(), empty()); - assert_that!(msg.optional_string_opt(), eq(Optional::Unset("".into()))); - assert_that!(msg.optional_string_mut(), is_unset()); msg.set_optional_string(""); assert_that!(*msg.optional_string().as_bytes(), empty()); assert_that!(msg.optional_string_opt(), eq(Optional::Set("".into()))); - - msg.optional_string_mut().clear(); - msg.optional_string_mut().or_default(); - assert_that!(*msg.optional_string().as_bytes(), empty()); - assert_that!(msg.optional_string_opt(), eq(Optional::Set("".into()))); } #[test] fn test_nested_enum_accessors() { - use TestAllTypes_::NestedEnum; + use test_all_types::NestedEnum; let mut msg = TestAllTypes::new(); assert_that!(msg.optional_nested_enum(), eq(NestedEnum::Zero)); - assert_that!(msg.optional_nested_enum_mut().get(), eq(NestedEnum::Zero)); msg.set_optional_nested_enum(NestedEnum::Baz); - assert_that!(msg.optional_nested_enum_mut().get(), eq(NestedEnum::Baz)); assert_that!(msg.optional_nested_enum(), eq(NestedEnum::Baz)); msg.set_optional_nested_enum(NestedEnum::default()); assert_that!(msg.optional_nested_enum(), eq(NestedEnum::Zero)); - assert_that!(msg.optional_nested_enum_mut().get(), eq(NestedEnum::Zero)); } #[test] fn test_optional_nested_enum_accessors() { - use TestProto3Optional_::NestedEnum; + use test_proto3_optional::NestedEnum; let mut msg = TestProto3Optional::new(); assert_that!(msg.optional_nested_enum(), eq(NestedEnum::Unspecified)); assert_that!(msg.optional_nested_enum_opt(), eq(Optional::Unset(NestedEnum::Unspecified))); - assert_that!(msg.optional_nested_enum_mut().get(), eq(NestedEnum::Unspecified)); msg.set_optional_nested_enum(NestedEnum::Baz); - assert_that!(msg.optional_nested_enum_mut().get(), eq(NestedEnum::Baz)); assert_that!(msg.optional_nested_enum_opt(), eq(Optional::Set(NestedEnum::Baz))); assert_that!(msg.optional_nested_enum(), eq(NestedEnum::Baz)); msg.set_optional_nested_enum(NestedEnum::default()); assert_that!(msg.optional_nested_enum(), eq(NestedEnum::Unspecified)); assert_that!(msg.optional_nested_enum_opt(), eq(Optional::Set(NestedEnum::Unspecified))); - assert_that!(msg.optional_nested_enum_mut().get(), eq(NestedEnum::Unspecified)); - - msg.optional_nested_enum_mut().clear(); - assert_that!(msg.optional_nested_enum(), eq(NestedEnum::Unspecified)); - assert_that!(msg.optional_nested_enum_opt(), eq(Optional::Unset(NestedEnum::Unspecified))); - assert_that!(msg.optional_nested_enum_mut().get(), eq(NestedEnum::Unspecified)); - - let mut field_mut = msg.optional_nested_enum_mut().or_default(); - assert_that!(field_mut.get(), eq(NestedEnum::Unspecified)); - field_mut.set(NestedEnum::Bar); - assert_that!(msg.optional_nested_enum(), eq(NestedEnum::Bar)); - assert_that!(msg.optional_nested_enum_opt(), eq(Optional::Set(NestedEnum::Bar))); - assert_that!(msg.optional_nested_enum_mut().get(), eq(NestedEnum::Bar)); } #[test] @@ -247,20 +160,17 @@ fn test_foreign_enum_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_foreign_enum(), eq(ForeignEnum::ForeignZero)); - assert_that!(msg.optional_foreign_enum_mut().get(), eq(ForeignEnum::ForeignZero)); msg.set_optional_foreign_enum(ForeignEnum::ForeignBaz); - assert_that!(msg.optional_foreign_enum_mut().get(), eq(ForeignEnum::ForeignBaz)); assert_that!(msg.optional_foreign_enum(), eq(ForeignEnum::ForeignBaz)); msg.set_optional_foreign_enum(ForeignEnum::default()); assert_that!(msg.optional_foreign_enum(), eq(ForeignEnum::ForeignZero)); - assert_that!(msg.optional_foreign_enum_mut().get(), eq(ForeignEnum::ForeignZero)); } #[test] fn test_oneof_accessors() { - use TestAllTypes_::OneofField::*; + use test_all_types::OneofField::*; let mut msg = TestAllTypes::new(); assert_that!(msg.oneof_field(), matches_pattern!(not_set(_))); @@ -273,7 +183,7 @@ fn test_oneof_accessors() { assert_that!(msg.oneof_uint32_opt(), eq(Optional::Unset(0))); assert_that!(msg.oneof_field(), matches_pattern!(not_set(_))); - msg.oneof_nested_message_mut().or_default(); // Cause the nested_message field to become set. + msg.oneof_nested_message_mut(); // Cause the nested_message field to become set. assert_that!(msg.oneof_bytes_opt(), matches_pattern!(Optional::Unset(_))); assert_that!(msg.oneof_field(), matches_pattern!(OneofNestedMessage(_))); @@ -283,13 +193,13 @@ fn test_oneof_accessors() { assert_that!(msg.oneof_uint32_opt(), eq(Optional::Unset(0))); assert_that!(msg.oneof_field(), matches_pattern!(OneofBytes(eq(b"123")))); - msg.oneof_bytes_mut().clear(); + msg.clear_oneof_bytes(); assert_that!(msg.oneof_field(), matches_pattern!(not_set(_))); } #[test] fn test_oneof_accessors_view_long_lifetime() { - use TestAllTypes_::OneofField::*; + use test_all_types::OneofField::*; let mut msg = TestAllTypes::new(); msg.set_oneof_uint32(7); @@ -306,80 +216,24 @@ fn test_oneof_accessors_view_long_lifetime() { #[test] fn test_oneof_enum_accessors() { use unittest_proto3::{ + test_oneof2::{Foo, FooCase, NestedEnum}, TestOneof2, - TestOneof2_::{Foo, NestedEnum}, }; let mut msg = TestOneof2::new(); assert_that!(msg.foo_enum_opt(), eq(Optional::Unset(NestedEnum::Unknown))); assert_that!(msg.foo(), matches_pattern!(Foo::not_set(_))); + assert_that!(msg.foo_case(), matches_pattern!(FooCase::not_set)); msg.set_foo_enum(NestedEnum::Bar); assert_that!(msg.foo_enum_opt(), eq(Optional::Set(NestedEnum::Bar))); assert_that!(msg.foo(), matches_pattern!(Foo::FooEnum(eq(NestedEnum::Bar)))); -} - -#[test] -fn test_oneof_mut_accessors() { - use TestAllTypes_::OneofFieldMut::*; - - let mut msg = TestAllTypes::new(); - assert_that!(msg.oneof_field_mut(), matches_pattern!(not_set(_))); - - msg.set_oneof_uint32(7); - - match msg.oneof_field_mut() { - OneofUint32(mut v) => { - assert_that!(v.get(), eq(7)); - v.set(8); - assert_that!(v.get(), eq(8)); - } - f => panic!("unexpected field_mut type! {:?}", f), - } - - // Confirm that the mut write above applies to both the field accessor and the - // oneof view accessor. - assert_that!(msg.oneof_uint32_opt(), eq(Optional::Set(8))); - assert_that!( - msg.oneof_field(), - matches_pattern!(TestAllTypes_::OneofField::OneofUint32(eq(8))) - ); - - // Clearing a different field in the same oneof doesn't affect the other, set - // field. - msg.clear_oneof_bytes(); - assert_that!( - msg.oneof_field(), - matches_pattern!(TestAllTypes_::OneofField::OneofUint32(eq(8))) - ); - - msg.clear_oneof_uint32(); - assert_that!(msg.oneof_field_mut(), matches_pattern!(not_set(_))); - - msg.set_oneof_uint32(7); - msg.set_oneof_bytes(b"123"); - assert_that!(msg.oneof_field_mut(), matches_pattern!(OneofBytes(_))); -} - -#[test] -fn test_oneof_mut_enum_accessors() { - use unittest_proto3::{ - TestOneof2, - TestOneof2_::{FooMut, NestedEnum}, - }; - - let mut msg = TestOneof2::new(); - assert_that!(msg.foo_enum_opt(), eq(Optional::Unset(NestedEnum::Unknown))); - assert_that!(msg.foo_mut(), matches_pattern!(FooMut::not_set(_))); - - msg.set_foo_enum(NestedEnum::Bar); - assert_that!(msg.foo_enum_opt(), eq(Optional::Set(NestedEnum::Bar))); - assert_that!(msg.foo_mut(), matches_pattern!(FooMut::FooEnum(_))); + assert_that!(msg.foo_case(), matches_pattern!(FooCase::FooEnum)); } #[test] fn test_submsg_setter() { - use TestAllTypes_::*; + use test_all_types::*; let mut nested = NestedMessage::new(); nested.set_bb(7); diff --git a/rust/test/shared/accessors_repeated_test.rs b/rust/test/shared/accessors_repeated_test.rs index 132513cf50..9aee4907ea 100644 --- a/rust/test/shared/accessors_repeated_test.rs +++ b/rust/test/shared/accessors_repeated_test.rs @@ -8,7 +8,7 @@ use googletest::prelude::*; use paste::paste; use protobuf::ViewProxy; -use unittest_proto::{TestAllTypes, TestAllTypes_, TestAllTypes_::NestedMessage}; +use unittest_proto::{test_all_types, test_all_types::NestedMessage, TestAllTypes}; macro_rules! generate_repeated_numeric_test { ($(($t: ty, $field: ident)),*) => { @@ -138,7 +138,7 @@ fn test_repeated_bool_accessors() { #[test] fn test_repeated_enum_accessors() { - use TestAllTypes_::NestedEnum; + use test_all_types::NestedEnum; let mut msg = TestAllTypes::new(); assert_that!(msg.repeated_nested_enum(), empty()); @@ -193,7 +193,7 @@ fn test_repeated_message() { let mut msg = TestAllTypes::new(); assert_that!(msg.repeated_nested_message().len(), eq(0)); let mut nested = NestedMessage::new(); - nested.bb_mut().set(1); + nested.set_bb(1); msg.repeated_nested_message_mut().push(nested.as_view()); assert_that!(msg.repeated_nested_message().get(0).unwrap().bb(), eq(1)); @@ -202,7 +202,7 @@ fn test_repeated_message() { assert_that!(msg2.repeated_nested_message().get(0).unwrap().bb(), eq(1)); let mut nested2 = NestedMessage::new(); - nested2.bb_mut().set(2); + nested2.set_bb(2); // TODO: b/320936046 - Test SettableValue once available msg.repeated_nested_message_mut().set(0, nested2.as_view()); diff --git a/rust/test/shared/accessors_test.rs b/rust/test/shared/accessors_test.rs index b9a5565b8b..fa11b86d07 100644 --- a/rust/test/shared/accessors_test.rs +++ b/rust/test/shared/accessors_test.rs @@ -8,13 +8,12 @@ //! Tests covering accessors for singular bool, int32, int64, and bytes fields. use googletest::prelude::*; -use matchers::{is_set, is_unset}; use protobuf::{MutProxy, Optional}; -use unittest_proto::{TestAllTypes, TestAllTypes_}; +use unittest_proto::{test_all_types, TestAllTypes}; #[test] fn test_default_accessors() { - let msg = TestAllTypes::new(); + let msg: TestAllTypes = Default::default(); assert_that!( msg, matches_pattern!(TestAllTypes{ @@ -40,22 +39,17 @@ fn test_default_accessors() { #[test] fn test_optional_fixed32_accessors() { let mut msg = TestAllTypes::new(); - assert_that!(msg.optional_fixed32_opt(), eq(Optional::Unset(0))); - assert_that!(msg.optional_fixed32(), eq(0)); - - msg.optional_fixed32_mut().set(99); - assert_that!(msg.optional_fixed32_opt(), eq(Optional::Set(99))); - assert_that!(msg.optional_fixed32(), eq(99)); - - msg.optional_fixed32_mut().clear(); + assert_that!(msg.has_optional_fixed32(), eq(false)); assert_that!(msg.optional_fixed32_opt(), eq(Optional::Unset(0))); assert_that!(msg.optional_fixed32(), eq(0)); msg.set_optional_fixed32(7); + assert_that!(msg.has_optional_fixed32(), eq(true)); assert_that!(msg.optional_fixed32_opt(), eq(Optional::Set(7))); assert_that!(msg.optional_fixed32(), eq(7)); msg.clear_optional_fixed32(); + assert_that!(msg.has_optional_fixed32(), eq(false)); assert_that!(msg.optional_fixed32_opt(), eq(Optional::Unset(0))); assert_that!(msg.optional_fixed32(), eq(0)); } @@ -64,33 +58,18 @@ fn test_optional_fixed32_accessors() { fn test_default_fixed32_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_fixed32(), eq(47)); - assert_that!(msg.default_fixed32_mut().get(), eq(47)); - assert_that!(msg.default_fixed32_mut().is_set(), eq(false)); + assert_that!(msg.has_default_fixed32(), eq(false)); assert_that!(msg.default_fixed32_opt(), eq(Optional::Unset(47))); msg.set_default_fixed32(7); assert_that!(msg.default_fixed32(), eq(7)); - assert_that!(msg.default_fixed32_mut().get(), eq(7)); - assert_that!(msg.default_fixed32_mut().is_set(), eq(true)); + assert_that!(msg.has_default_fixed32(), eq(true)); assert_that!(msg.default_fixed32_opt(), eq(Optional::Set(7))); - msg.default_fixed32_mut().set(999); - assert_that!(msg.default_fixed32(), eq(999)); - assert_that!(msg.default_fixed32_mut().get(), eq(999)); - assert_that!(msg.default_fixed32_mut().is_set(), eq(true)); - assert_that!(msg.default_fixed32_opt(), eq(Optional::Set(999))); - - msg.default_fixed32_mut().clear(); + msg.clear_default_fixed32(); assert_that!(msg.default_fixed32(), eq(47)); - assert_that!(msg.default_fixed32_mut().get(), eq(47)); - assert_that!(msg.default_fixed32_mut().is_set(), eq(false)); + assert_that!(msg.has_default_fixed32(), eq(false)); assert_that!(msg.default_fixed32_opt(), eq(Optional::Unset(47))); - - msg.default_fixed32_mut().or_default(); - assert_that!(msg.default_fixed32(), eq(47)); - assert_that!(msg.default_fixed32_mut().get(), eq(47)); - assert_that!(msg.default_fixed32_mut().is_set(), eq(true)); - assert_that!(msg.default_fixed32_opt(), eq(Optional::Set(47))); } #[test] @@ -103,11 +82,11 @@ fn test_optional_fixed64_accessors() { assert_that!(msg.optional_fixed64_opt(), eq(Optional::Set(99))); assert_that!(msg.optional_fixed64(), eq(99)); - msg.optional_fixed64_mut().set(2000); + msg.set_optional_fixed64(2000); assert_that!(msg.optional_fixed64_opt(), eq(Optional::Set(2000))); assert_that!(msg.optional_fixed64(), eq(2000)); - msg.optional_fixed64_mut().clear(); + msg.clear_optional_fixed64(); assert_that!(msg.optional_fixed64_opt(), eq(Optional::Unset(0))); assert_that!(msg.optional_fixed64(), eq(0)); } @@ -116,33 +95,19 @@ fn test_optional_fixed64_accessors() { fn test_default_fixed64_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_fixed64(), eq(48)); - assert_that!(msg.default_fixed64_mut().get(), eq(48)); - assert_that!(msg.default_fixed64_mut().is_set(), eq(false)); assert_that!(msg.default_fixed64_opt(), eq(Optional::Unset(48))); msg.set_default_fixed64(4); assert_that!(msg.default_fixed64(), eq(4)); - assert_that!(msg.default_fixed64_mut().get(), eq(4)); - assert_that!(msg.default_fixed64_mut().is_set(), eq(true)); assert_that!(msg.default_fixed64_opt(), eq(Optional::Set(4))); - msg.default_fixed64_mut().set(999); + msg.set_default_fixed64(999); assert_that!(msg.default_fixed64(), eq(999)); - assert_that!(msg.default_fixed64_mut().get(), eq(999)); - assert_that!(msg.default_fixed64_mut().is_set(), eq(true)); assert_that!(msg.default_fixed64_opt(), eq(Optional::Set(999))); - msg.default_fixed64_mut().clear(); + msg.clear_default_fixed64(); assert_that!(msg.default_fixed64(), eq(48)); - assert_that!(msg.default_fixed64_mut().get(), eq(48)); - assert_that!(msg.default_fixed64_mut().is_set(), eq(false)); assert_that!(msg.default_fixed64_opt(), eq(Optional::Unset(48))); - - msg.default_fixed64_mut().or_default(); - assert_that!(msg.default_fixed64(), eq(48)); - assert_that!(msg.default_fixed64_mut().get(), eq(48)); - assert_that!(msg.default_fixed64_mut().is_set(), eq(true)); - assert_that!(msg.default_fixed64_opt(), eq(Optional::Set(48))); } #[test] @@ -155,11 +120,11 @@ fn test_optional_int32_accessors() { assert_that!(msg.optional_int32_opt(), eq(Optional::Set(0))); assert_that!(msg.optional_int32(), eq(0)); - msg.optional_int32_mut().set(1); + msg.set_optional_int32(1); assert_that!(msg.optional_int32_opt(), eq(Optional::Set(1))); assert_that!(msg.optional_int32(), eq(1)); - msg.optional_int32_mut().clear(); + msg.clear_optional_int32(); assert_that!(msg.optional_int32_opt(), eq(Optional::Unset(0))); assert_that!(msg.optional_int32(), eq(0)); } @@ -168,39 +133,23 @@ fn test_optional_int32_accessors() { fn test_default_int32_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_int32(), eq(41)); - assert_that!(msg.default_int32_mut().get(), eq(41)); - assert_that!(msg.default_int32_mut().is_set(), eq(false)); assert_that!(msg.default_int32_opt(), eq(Optional::Unset(41))); msg.set_default_int32(41); assert_that!(msg.default_int32(), eq(41)); - assert_that!(msg.default_int32_mut().get(), eq(41)); - assert_that!(msg.default_int32_mut().is_set(), eq(true)); assert_that!(msg.default_int32_opt(), eq(Optional::Set(41))); msg.clear_default_int32(); assert_that!(msg.default_int32(), eq(41)); - assert_that!(msg.default_int32_mut().get(), eq(41)); - assert_that!(msg.default_int32_mut().is_set(), eq(false)); assert_that!(msg.default_int32_opt(), eq(Optional::Unset(41))); - msg.default_int32_mut().set(999); + msg.set_default_int32(999); assert_that!(msg.default_int32(), eq(999)); - assert_that!(msg.default_int32_mut().get(), eq(999)); - assert_that!(msg.default_int32_mut().is_set(), eq(true)); assert_that!(msg.default_int32_opt(), eq(Optional::Set(999))); - msg.default_int32_mut().clear(); + msg.clear_default_int32(); assert_that!(msg.default_int32(), eq(41)); - assert_that!(msg.default_int32_mut().get(), eq(41)); - assert_that!(msg.default_int32_mut().is_set(), eq(false)); assert_that!(msg.default_int32_opt(), eq(Optional::Unset(41))); - - msg.default_int32_mut().or_default(); - assert_that!(msg.default_int32(), eq(41)); - assert_that!(msg.default_int32_mut().get(), eq(41)); - assert_that!(msg.default_int32_mut().is_set(), eq(true)); - assert_that!(msg.default_int32_opt(), eq(Optional::Set(41))); } #[test] @@ -209,11 +158,11 @@ fn test_optional_int64_accessors() { assert_that!(msg.optional_int64_opt(), eq(Optional::Unset(0))); assert_that!(msg.optional_int64(), eq(0)); - msg.optional_int64_mut().set(42); + msg.set_optional_int64(42); assert_that!(msg.optional_int64_opt(), eq(Optional::Set(42))); assert_that!(msg.optional_int64(), eq(42)); - msg.optional_int64_mut().clear(); + msg.clear_optional_int64(); assert_that!(msg.optional_int64_opt(), eq(Optional::Unset(0))); assert_that!(msg.optional_int64(), eq(0)); } @@ -222,27 +171,15 @@ fn test_optional_int64_accessors() { fn test_default_int64_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_int64(), eq(42)); - assert_that!(msg.default_int64_mut().get(), eq(42)); - assert_that!(msg.default_int64_mut().is_set(), eq(false)); assert_that!(msg.default_int64_opt(), eq(Optional::Unset(42))); - msg.default_int64_mut().set(999); + msg.set_default_int64(999); assert_that!(msg.default_int64(), eq(999)); - assert_that!(msg.default_int64_mut().get(), eq(999)); - assert_that!(msg.default_int64_mut().is_set(), eq(true)); assert_that!(msg.default_int64_opt(), eq(Optional::Set(999))); - msg.default_int64_mut().clear(); + msg.clear_default_int64(); assert_that!(msg.default_int64(), eq(42)); - assert_that!(msg.default_int64_mut().get(), eq(42)); - assert_that!(msg.default_int64_mut().is_set(), eq(false)); assert_that!(msg.default_int64_opt(), eq(Optional::Unset(42))); - - msg.default_int64_mut().or_default(); - assert_that!(msg.default_int64(), eq(42)); - assert_that!(msg.default_int64_mut().get(), eq(42)); - assert_that!(msg.default_int64_mut().is_set(), eq(true)); - assert_that!(msg.default_int64_opt(), eq(Optional::Set(42))); } #[test] @@ -251,11 +188,11 @@ fn test_optional_sint32_accessors() { assert_that!(msg.optional_sint32_opt(), eq(Optional::Unset(0))); assert_that!(msg.optional_sint32(), eq(0)); - msg.optional_sint32_mut().set(-22); + msg.set_optional_sint32(-22); assert_that!(msg.optional_sint32_opt(), eq(Optional::Set(-22))); assert_that!(msg.optional_sint32(), eq(-22)); - msg.optional_sint32_mut().clear(); + msg.clear_optional_sint32(); assert_that!(msg.optional_sint32_opt(), eq(Optional::Unset(0))); assert_that!(msg.optional_sint32(), eq(0)); } @@ -264,27 +201,15 @@ fn test_optional_sint32_accessors() { fn test_default_sint32_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_sint32(), eq(-45)); - assert_that!(msg.default_sint32_mut().get(), eq(-45)); - assert_that!(msg.default_sint32_mut().is_set(), eq(false)); assert_that!(msg.default_sint32_opt(), eq(Optional::Unset(-45))); - msg.default_sint32_mut().set(999); + msg.set_default_sint32(999); assert_that!(msg.default_sint32(), eq(999)); - assert_that!(msg.default_sint32_mut().get(), eq(999)); - assert_that!(msg.default_sint32_mut().is_set(), eq(true)); assert_that!(msg.default_sint32_opt(), eq(Optional::Set(999))); - msg.default_sint32_mut().clear(); + msg.clear_default_sint32(); assert_that!(msg.default_sint32(), eq(-45)); - assert_that!(msg.default_sint32_mut().get(), eq(-45)); - assert_that!(msg.default_sint32_mut().is_set(), eq(false)); assert_that!(msg.default_sint32_opt(), eq(Optional::Unset(-45))); - - msg.default_sint32_mut().or_default(); - assert_that!(msg.default_sint32(), eq(-45)); - assert_that!(msg.default_sint32_mut().get(), eq(-45)); - assert_that!(msg.default_sint32_mut().is_set(), eq(true)); - assert_that!(msg.default_sint32_opt(), eq(Optional::Set(-45))); } #[test] @@ -293,11 +218,11 @@ fn test_optional_sint64_accessors() { assert_that!(msg.optional_sint64_opt(), eq(Optional::Unset(0))); assert_that!(msg.optional_sint64(), eq(0)); - msg.optional_sint64_mut().set(7000); + msg.set_optional_sint64(7000); assert_that!(msg.optional_sint64_opt(), eq(Optional::Set(7000))); assert_that!(msg.optional_sint64(), eq(7000)); - msg.optional_sint64_mut().clear(); + msg.clear_optional_sint64(); assert_that!(msg.optional_sint64_opt(), eq(Optional::Unset(0))); assert_that!(msg.optional_sint64(), eq(0)); } @@ -306,27 +231,15 @@ fn test_optional_sint64_accessors() { fn test_default_sint64_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_sint64(), eq(46)); - assert_that!(msg.default_sint64_mut().get(), eq(46)); - assert_that!(msg.default_sint64_mut().is_set(), eq(false)); assert_that!(msg.default_sint64_opt(), eq(Optional::Unset(46))); - msg.default_sint64_mut().set(999); + msg.set_default_sint64(999); assert_that!(msg.default_sint64(), eq(999)); - assert_that!(msg.default_sint64_mut().get(), eq(999)); - assert_that!(msg.default_sint64_mut().is_set(), eq(true)); assert_that!(msg.default_sint64_opt(), eq(Optional::Set(999))); - msg.default_sint64_mut().clear(); + msg.clear_default_sint64(); assert_that!(msg.default_sint64(), eq(46)); - assert_that!(msg.default_sint64_mut().get(), eq(46)); - assert_that!(msg.default_sint64_mut().is_set(), eq(false)); assert_that!(msg.default_sint64_opt(), eq(Optional::Unset(46))); - - msg.default_sint64_mut().or_default(); - assert_that!(msg.default_sint64(), eq(46)); - assert_that!(msg.default_sint64_mut().get(), eq(46)); - assert_that!(msg.default_sint64_mut().is_set(), eq(true)); - assert_that!(msg.default_sint64_opt(), eq(Optional::Set(46))); } #[test] @@ -335,11 +248,11 @@ fn test_optional_uint32_accessors() { assert_that!(msg.optional_uint32_opt(), eq(Optional::Unset(0))); assert_that!(msg.optional_uint32(), eq(0)); - msg.optional_uint32_mut().set(9001); + msg.set_optional_uint32(9001); assert_that!(msg.optional_uint32_opt(), eq(Optional::Set(9001))); assert_that!(msg.optional_uint32(), eq(9001)); - msg.optional_uint32_mut().clear(); + msg.clear_optional_uint32(); assert_that!(msg.optional_uint32_opt(), eq(Optional::Unset(0))); assert_that!(msg.optional_uint32(), eq(0)); } @@ -348,27 +261,15 @@ fn test_optional_uint32_accessors() { fn test_default_uint32_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_uint32(), eq(43)); - assert_that!(msg.default_uint32_mut().get(), eq(43)); - assert_that!(msg.default_uint32_mut().is_set(), eq(false)); assert_that!(msg.default_uint32_opt(), eq(Optional::Unset(43))); - msg.default_uint32_mut().set(999); + msg.set_default_uint32(999); assert_that!(msg.default_uint32(), eq(999)); - assert_that!(msg.default_uint32_mut().get(), eq(999)); - assert_that!(msg.default_uint32_mut().is_set(), eq(true)); assert_that!(msg.default_uint32_opt(), eq(Optional::Set(999))); - msg.default_uint32_mut().clear(); + msg.clear_default_uint32(); assert_that!(msg.default_uint32(), eq(43)); - assert_that!(msg.default_uint32_mut().get(), eq(43)); - assert_that!(msg.default_uint32_mut().is_set(), eq(false)); assert_that!(msg.default_uint32_opt(), eq(Optional::Unset(43))); - - msg.default_uint32_mut().or_default(); - assert_that!(msg.default_uint32(), eq(43)); - assert_that!(msg.default_uint32_mut().get(), eq(43)); - assert_that!(msg.default_uint32_mut().is_set(), eq(true)); - assert_that!(msg.default_uint32_opt(), eq(Optional::Set(43))); } #[test] @@ -377,11 +278,11 @@ fn test_optional_uint64_accessors() { assert_that!(msg.optional_uint64_opt(), eq(Optional::Unset(0))); assert_that!(msg.optional_uint64(), eq(0)); - msg.optional_uint64_mut().set(42); + msg.set_optional_uint64(42); assert_that!(msg.optional_uint64_opt(), eq(Optional::Set(42))); assert_that!(msg.optional_uint64(), eq(42)); - msg.optional_uint64_mut().clear(); + msg.clear_optional_uint64(); assert_that!(msg.optional_uint64_opt(), eq(Optional::Unset(0))); assert_that!(msg.optional_uint64(), eq(0)); } @@ -390,27 +291,15 @@ fn test_optional_uint64_accessors() { fn test_default_uint64_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_uint64(), eq(44)); - assert_that!(msg.default_uint64_mut().get(), eq(44)); - assert_that!(msg.default_uint64_mut().is_set(), eq(false)); assert_that!(msg.default_uint64_opt(), eq(Optional::Unset(44))); - msg.default_uint64_mut().set(999); + msg.set_default_uint64(999); assert_that!(msg.default_uint64(), eq(999)); - assert_that!(msg.default_uint64_mut().get(), eq(999)); - assert_that!(msg.default_uint64_mut().is_set(), eq(true)); assert_that!(msg.default_uint64_opt(), eq(Optional::Set(999))); - msg.default_uint64_mut().clear(); + msg.clear_default_uint64(); assert_that!(msg.default_uint64(), eq(44)); - assert_that!(msg.default_uint64_mut().get(), eq(44)); - assert_that!(msg.default_uint64_mut().is_set(), eq(false)); assert_that!(msg.default_uint64_opt(), eq(Optional::Unset(44))); - - msg.default_uint64_mut().or_default(); - assert_that!(msg.default_uint64(), eq(44)); - assert_that!(msg.default_uint64_mut().get(), eq(44)); - assert_that!(msg.default_uint64_mut().is_set(), eq(true)); - assert_that!(msg.default_uint64_opt(), eq(Optional::Set(44))); } #[test] @@ -419,11 +308,11 @@ fn test_optional_float_accessors() { assert_that!(msg.optional_float_opt(), eq(Optional::Unset(0.0))); assert_that!(msg.optional_float(), eq(0.0)); - msg.optional_float_mut().set(std::f32::consts::PI); + msg.set_optional_float(std::f32::consts::PI); assert_that!(msg.optional_float_opt(), eq(Optional::Set(std::f32::consts::PI))); assert_that!(msg.optional_float(), eq(std::f32::consts::PI)); - msg.optional_float_mut().clear(); + msg.clear_optional_float(); assert_that!(msg.optional_float_opt(), eq(Optional::Unset(0.0))); assert_that!(msg.optional_float(), eq(0.0)); } @@ -432,27 +321,15 @@ fn test_optional_float_accessors() { fn test_default_float_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_float(), eq(51.5)); - assert_that!(msg.default_float_mut().get(), eq(51.5)); - assert_that!(msg.default_float_mut().is_set(), eq(false)); assert_that!(msg.default_float_opt(), eq(Optional::Unset(51.5))); - msg.default_float_mut().set(999.9); + msg.set_default_float(999.9); assert_that!(msg.default_float(), eq(999.9)); - assert_that!(msg.default_float_mut().get(), eq(999.9)); - assert_that!(msg.default_float_mut().is_set(), eq(true)); assert_that!(msg.default_float_opt(), eq(Optional::Set(999.9))); - msg.default_float_mut().clear(); + msg.clear_default_float(); assert_that!(msg.default_float(), eq(51.5)); - assert_that!(msg.default_float_mut().get(), eq(51.5)); - assert_that!(msg.default_float_mut().is_set(), eq(false)); assert_that!(msg.default_float_opt(), eq(Optional::Unset(51.5))); - - msg.default_float_mut().or_default(); - assert_that!(msg.default_float(), eq(51.5)); - assert_that!(msg.default_float_mut().get(), eq(51.5)); - assert_that!(msg.default_float_mut().is_set(), eq(true)); - assert_that!(msg.default_float_opt(), eq(Optional::Set(51.5))); } #[test] @@ -461,11 +338,11 @@ fn test_optional_double_accessors() { assert_that!(msg.optional_double_opt(), eq(Optional::Unset(0.0))); assert_that!(msg.optional_double(), eq(0.0)); - msg.optional_double_mut().set(-10.99); + msg.set_optional_double(-10.99); assert_that!(msg.optional_double_opt(), eq(Optional::Set(-10.99))); assert_that!(msg.optional_double(), eq(-10.99)); - msg.optional_double_mut().clear(); + msg.clear_optional_double(); assert_that!(msg.optional_double_opt(), eq(Optional::Unset(0.0))); assert_that!(msg.optional_double(), eq(0.0)); } @@ -474,27 +351,15 @@ fn test_optional_double_accessors() { fn test_default_double_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_double(), eq(52e3)); - assert_that!(msg.default_double_mut().get(), eq(52e3)); - assert_that!(msg.default_double_mut().is_set(), eq(false)); assert_that!(msg.default_double_opt(), eq(Optional::Unset(52e3))); - msg.default_double_mut().set(999.9); + msg.set_default_double(999.9); assert_that!(msg.default_double(), eq(999.9)); - assert_that!(msg.default_double_mut().get(), eq(999.9)); - assert_that!(msg.default_double_mut().is_set(), eq(true)); assert_that!(msg.default_double_opt(), eq(Optional::Set(999.9))); - msg.default_double_mut().clear(); + msg.clear_default_double(); assert_that!(msg.default_double(), eq(52e3)); - assert_that!(msg.default_double_mut().get(), eq(52e3)); - assert_that!(msg.default_double_mut().is_set(), eq(false)); assert_that!(msg.default_double_opt(), eq(Optional::Unset(52e3))); - - msg.default_double_mut().or_default(); - assert_that!(msg.default_double(), eq(52e3)); - assert_that!(msg.default_double_mut().get(), eq(52e3)); - assert_that!(msg.default_double_mut().is_set(), eq(true)); - assert_that!(msg.default_double_opt(), eq(Optional::Set(52e3))); } #[test] @@ -502,10 +367,10 @@ fn test_optional_bool_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_bool_opt(), eq(Optional::Unset(false))); - msg.optional_bool_mut().set(true); + msg.set_optional_bool(true); assert_that!(msg.optional_bool_opt(), eq(Optional::Set(true))); - msg.optional_bool_mut().clear(); + msg.clear_optional_bool(); assert_that!(msg.optional_bool_opt(), eq(Optional::Unset(false))); } @@ -513,123 +378,70 @@ fn test_optional_bool_accessors() { fn test_default_bool_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_bool(), eq(true)); - assert_that!(msg.default_bool_mut().get(), eq(true)); - assert_that!(msg.default_bool_mut().is_set(), eq(false)); assert_that!(msg.default_bool_opt(), eq(Optional::Unset(true))); - msg.default_bool_mut().set(false); + msg.set_default_bool(false); assert_that!(msg.default_bool(), eq(false)); - assert_that!(msg.default_bool_mut().get(), eq(false)); - assert_that!(msg.default_bool_mut().is_set(), eq(true)); assert_that!(msg.default_bool_opt(), eq(Optional::Set(false))); - msg.default_bool_mut().clear(); + msg.clear_default_bool(); assert_that!(msg.default_bool(), eq(true)); - assert_that!(msg.default_bool_mut().get(), eq(true)); - assert_that!(msg.default_bool_mut().is_set(), eq(false)); assert_that!(msg.default_bool_opt(), eq(Optional::Unset(true))); - - msg.default_bool_mut().or_default(); - assert_that!(msg.default_bool(), eq(true)); - assert_that!(msg.default_bool_mut().get(), eq(true)); - assert_that!(msg.default_bool_mut().is_set(), eq(true)); - assert_that!(msg.default_bool_opt(), eq(Optional::Set(true))); } #[test] fn test_optional_bytes_accessors() { let mut msg = TestAllTypes::new(); assert_that!(*msg.optional_bytes(), empty()); + assert_that!(msg.has_optional_bytes(), eq(false)); assert_that!(msg.optional_bytes_opt(), eq(Optional::Unset(&b""[..]))); - assert_that!(*msg.optional_bytes_mut().get(), empty()); - assert_that!(msg.optional_bytes_mut(), is_unset()); { let s = Vec::from(&b"hello world"[..]); - msg.optional_bytes_mut().set(&s[..]); + msg.set_optional_bytes(&s[..]); } assert_that!(msg.optional_bytes(), eq(b"hello world")); + assert_that!(msg.has_optional_bytes(), eq(true)); assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b"hello world"[..]))); - assert_that!(msg.optional_bytes_mut(), is_set()); - assert_that!(msg.optional_bytes_mut().get(), eq(b"hello world")); - - msg.optional_bytes_mut().or_default().set(b"accessors_test"); - assert_that!(msg.optional_bytes(), eq(b"accessors_test")); - assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b"accessors_test"[..]))); - assert_that!(msg.optional_bytes_mut(), is_set()); - assert_that!(msg.optional_bytes_mut().get(), eq(b"accessors_test")); - assert_that!(msg.optional_bytes_mut().or_default().get(), eq(b"accessors_test")); - msg.optional_bytes_mut().clear(); + msg.clear_optional_bytes(); assert_that!(*msg.optional_bytes(), empty()); + assert_that!(msg.has_optional_bytes(), eq(false)); assert_that!(msg.optional_bytes_opt(), eq(Optional::Unset(&b""[..]))); - assert_that!(msg.optional_bytes_mut(), is_unset()); - msg.optional_bytes_mut().set(b""); + msg.set_optional_bytes(b""); assert_that!(*msg.optional_bytes(), empty()); + assert_that!(msg.has_optional_bytes(), eq(true)); assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b""[..]))); - - msg.optional_bytes_mut().clear(); - msg.optional_bytes_mut().or_default(); - assert_that!(*msg.optional_bytes(), empty()); - assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b""[..]))); - - msg.optional_bytes_mut().or_default().set(b"\xffbinary\x85non-utf8"); - assert_that!(msg.optional_bytes(), eq(b"\xffbinary\x85non-utf8")); - assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b"\xffbinary\x85non-utf8"[..]))); - assert_that!(msg.optional_bytes_mut(), is_set()); - assert_that!(msg.optional_bytes_mut().get(), eq(b"\xffbinary\x85non-utf8")); - assert_that!(msg.optional_bytes_mut().or_default().get(), eq(b"\xffbinary\x85non-utf8")); } #[test] fn test_nonempty_default_bytes_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_bytes(), eq(b"world")); + assert_that!(msg.has_default_bytes(), eq(false)); assert_that!(msg.default_bytes_opt(), eq(Optional::Unset(&b"world"[..]))); - assert_that!(msg.default_bytes_mut().get(), eq(b"world")); - assert_that!(msg.default_bytes_mut(), is_unset()); { let s = String::from("hello world"); - msg.default_bytes_mut().set(s.as_bytes()); + msg.set_default_bytes(s.as_bytes()); } assert_that!(msg.default_bytes(), eq(b"hello world")); + assert_that!(msg.has_default_bytes(), eq(true)); assert_that!(msg.default_bytes_opt(), eq(Optional::Set(&b"hello world"[..]))); - assert_that!(msg.default_bytes_mut(), is_set()); - assert_that!(msg.default_bytes_mut().get(), eq(b"hello world")); - - msg.default_bytes_mut().or_default().set(b"accessors_test"); - assert_that!(msg.default_bytes(), eq(b"accessors_test")); - assert_that!(msg.default_bytes_opt(), eq(Optional::Set(&b"accessors_test"[..]))); - assert_that!(msg.default_bytes_mut(), is_set()); - assert_that!(msg.default_bytes_mut().get(), eq(b"accessors_test")); - assert_that!(msg.default_bytes_mut().or_default().get(), eq(b"accessors_test")); - msg.default_bytes_mut().clear(); + msg.clear_default_bytes(); assert_that!(msg.default_bytes(), eq(b"world")); + assert_that!(msg.has_default_bytes(), eq(false)); assert_that!(msg.default_bytes_opt(), eq(Optional::Unset(&b"world"[..]))); - assert_that!(msg.default_bytes_mut(), is_unset()); msg.set_default_bytes(b""); assert_that!(*msg.default_bytes(), empty()); assert_that!(msg.default_bytes_opt(), eq(Optional::Set(&b""[..]))); - msg.default_bytes_mut().clear(); - msg.default_bytes_mut().or_default(); - assert_that!(msg.default_bytes(), eq(b"world")); - assert_that!(msg.default_bytes_opt(), eq(Optional::Set(&b"world"[..]))); - msg.clear_default_bytes(); + assert_that!(msg.default_bytes(), eq(b"world")); assert_that!(msg.default_bytes_opt(), eq(Optional::Unset(&b"world"[..]))); - assert_that!(msg.default_bytes_mut(), is_unset()); - - msg.default_bytes_mut().or_default().set(b"\xffbinary\x85non-utf8"); - assert_that!(msg.default_bytes(), eq(b"\xffbinary\x85non-utf8")); - assert_that!(msg.default_bytes_opt(), eq(Optional::Set(&b"\xffbinary\x85non-utf8"[..]))); - assert_that!(msg.default_bytes_mut(), is_set()); - assert_that!(msg.default_bytes_mut().get(), eq(b"\xffbinary\x85non-utf8")); - assert_that!(msg.default_bytes_mut().or_default().get(), eq(b"\xffbinary\x85non-utf8")); } #[test] @@ -637,38 +449,25 @@ fn test_optional_string_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_string(), eq("")); assert_that!(msg.optional_string_opt(), eq(Optional::Unset("".into()))); - assert_that!(msg.optional_string_mut().get(), eq("")); - assert_that!(msg.optional_string_mut(), is_unset()); { let s = String::from("hello world"); - msg.optional_string_mut().set(&s[..]); + msg.set_optional_string(&s[..]); } assert_that!(msg.optional_string(), eq("hello world")); assert_that!(msg.optional_string_opt(), eq(Optional::Set("hello world".into()))); - assert_that!(msg.optional_string_mut(), is_set()); - assert_that!(msg.optional_string_mut().get(), eq("hello world")); - msg.optional_string_mut().or_default().set("accessors_test"); - assert_that!(msg.optional_string(), eq("accessors_test")); - assert_that!(msg.optional_string_opt(), eq(Optional::Set("accessors_test".into()))); - assert_that!(msg.optional_string_mut(), is_set()); - assert_that!(msg.optional_string_mut().get(), eq("accessors_test")); - assert_that!(msg.optional_string_mut().or_default().get(), eq("accessors_test")); - - msg.optional_string_mut().clear(); + msg.clear_optional_string(); assert_that!(msg.optional_string(), eq("")); assert_that!(msg.optional_string_opt(), eq(Optional::Unset("".into()))); - assert_that!(msg.optional_string_mut(), is_unset()); msg.set_optional_string(""); assert_that!(msg.optional_string(), eq("")); assert_that!(msg.optional_string_opt(), eq(Optional::Set("".into()))); msg.clear_optional_string(); - msg.optional_string_mut().or_default(); assert_that!(msg.optional_string(), eq("")); - assert_that!(msg.optional_string_opt(), eq(Optional::Set("".into()))); + assert_that!(msg.optional_string_opt(), eq(Optional::Unset("".into()))); } #[test] @@ -676,66 +475,57 @@ fn test_nonempty_default_string_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_string(), eq("hello")); assert_that!(msg.default_string_opt(), eq(Optional::Unset("hello".into()))); - assert_that!(msg.default_string_mut().get(), eq("hello")); - assert_that!(msg.default_string_mut(), is_unset()); { let s = String::from("hello world"); - msg.default_string_mut().set(&s[..]); + msg.set_default_string(&s[..]); } assert_that!(msg.default_string(), eq("hello world")); assert_that!(msg.default_string_opt(), eq(Optional::Set("hello world".into()))); - assert_that!(msg.default_string_mut(), is_set()); - assert_that!(msg.default_string_mut().get(), eq("hello world")); - - msg.default_string_mut().or_default().set("accessors_test"); - assert_that!(msg.default_string(), eq("accessors_test")); - assert_that!(msg.default_string_opt(), eq(Optional::Set("accessors_test".into()))); - assert_that!(msg.default_string_mut(), is_set()); - assert_that!(msg.default_string_mut().get(), eq("accessors_test")); - assert_that!(msg.default_string_mut().or_default().get(), eq("accessors_test")); - msg.default_string_mut().clear(); + msg.clear_default_string(); assert_that!(msg.default_string(), eq("hello")); assert_that!(msg.default_string_opt(), eq(Optional::Unset("hello".into()))); - assert_that!(msg.default_string_mut(), is_unset()); - msg.default_string_mut().set(""); + msg.set_default_string(""); assert_that!(msg.default_string(), eq("")); assert_that!(msg.default_string_opt(), eq(Optional::Set("".into()))); - msg.default_string_mut().clear(); - msg.default_string_mut().or_default(); + msg.clear_default_string(); assert_that!(msg.default_string(), eq("hello")); - assert_that!(msg.default_string_opt(), eq(Optional::Set("hello".into()))); + assert_that!(msg.default_string_opt(), eq(Optional::Unset("hello".into()))); } #[test] fn test_singular_msg_field() { - use TestAllTypes_::*; + use test_all_types::*; let mut msg = TestAllTypes::new(); - let msg_view: NestedMessageView = msg.optional_nested_message(); + let msg_view = msg.optional_nested_message(); // testing reading an int inside a view assert_that!(msg_view.bb(), eq(0)); - let mut nested_msg_mut: NestedMessageMut = msg.optional_nested_message_mut().or_default(); + assert_that!(msg.has_optional_nested_message(), eq(false)); + let mut nested_msg_mut = msg.optional_nested_message_mut(); + // test reading an int inside a mut assert_that!(nested_msg_mut.bb(), eq(0)); // Test setting an owned NestedMessage onto another message. let mut new_nested = NestedMessage::new(); - new_nested.bb_mut().set(7); + new_nested.set_bb(7); nested_msg_mut.set(new_nested); assert_that!(nested_msg_mut.bb(), eq(7)); + + assert_that!(msg.has_optional_nested_message(), eq(true)); } #[test] fn test_message_opt() { let msg = TestAllTypes::new(); let opt: Optional< - unittest_proto::TestAllTypes_::NestedMessageView<'_>, - unittest_proto::TestAllTypes_::NestedMessageView<'_>, + unittest_proto::test_all_types::NestedMessageView<'_>, + unittest_proto::test_all_types::NestedMessageView<'_>, > = msg.optional_nested_message_opt(); assert_that!(opt.is_set(), eq(false)); assert_that!(opt.into_inner().bb(), eq(0)); @@ -744,89 +534,81 @@ fn test_message_opt() { #[test] fn test_message_opt_set() { let mut msg = TestAllTypes::new(); - let submsg = TestAllTypes_::NestedMessage::new(); - + let submsg = test_all_types::NestedMessage::new(); + msg.set_optional_nested_message(submsg); + msg.clear_optional_nested_message(); assert_that!(msg.optional_nested_message_opt().is_set(), eq(false)); - msg.optional_nested_message_mut().set(submsg); - assert_that!(msg.optional_nested_message_opt().is_set(), eq(true)); - - msg.optional_nested_message_mut().clear(); - assert_that!(msg.optional_nested_message_mut().is_set(), eq(false)); } #[test] fn test_setting_submsg() { let mut msg = TestAllTypes::new(); - let submsg = TestAllTypes_::NestedMessage::new(); + let submsg = test_all_types::NestedMessage::new(); - let fieldentry = msg.optional_nested_message_mut(); - assert_that!(fieldentry.is_set(), eq(false)); + assert_that!(msg.has_optional_nested_message(), eq(false)); + assert_that!(msg.optional_nested_message_opt().is_set(), eq(false)); - fieldentry.or_default().set(submsg); + msg.set_optional_nested_message(submsg); // confirm that invoking .set on a submsg indeed flips the set bit - assert_that!(msg.optional_nested_message_mut().is_set(), eq(true)); + assert_that!(msg.has_optional_nested_message(), eq(true)); + assert_that!(msg.optional_nested_message_opt().is_set(), eq(true)); - msg.optional_nested_message_mut().clear(); - assert_that!(msg.optional_nested_message_mut().is_set(), eq(false)); + msg.clear_optional_nested_message(); + assert_that!(msg.has_optional_nested_message(), eq(false)); + assert_that!(msg.optional_nested_message_opt().is_set(), eq(false)); } #[test] -fn test_msg_or_default() { +fn test_msg_mut_initializes() { let mut msg = TestAllTypes::new(); - assert_that!(msg.optional_nested_message_mut().is_set(), eq(false)); + assert_that!(msg.has_optional_nested_message(), eq(false)); + assert_that!(msg.optional_nested_message_opt().is_set(), eq(false)); - let _ = msg.optional_nested_message_mut().or_default(); - // confirm that that or_default makes the field Present - assert_that!(msg.optional_nested_message_mut().is_set(), eq(true)); + let _ = msg.optional_nested_message_mut(); + // confirm that that optional_nested_message_mut makes the field Present + assert_that!(msg.has_optional_nested_message(), eq(true)); + assert_that!(msg.optional_nested_message_opt().is_set(), eq(true)); - msg.optional_nested_message_mut().clear(); - assert_that!(msg.optional_nested_message_mut().is_set(), eq(false)); + msg.clear_optional_nested_message(); + assert_that!(msg.has_optional_nested_message(), eq(false)); + assert_that!(msg.optional_nested_message_opt().is_set(), eq(false)); } #[test] fn test_optional_nested_enum_accessors() { - use TestAllTypes_::NestedEnum; + use test_all_types::NestedEnum; let mut msg = TestAllTypes::new(); + assert_that!(msg.has_optional_nested_enum(), eq(false)); assert_that!(msg.optional_nested_enum_opt(), eq(Optional::Unset(NestedEnum::Foo))); assert_that!(msg.optional_nested_enum(), eq(NestedEnum::Foo)); - msg.optional_nested_enum_mut().set(NestedEnum::Neg); + msg.set_optional_nested_enum(NestedEnum::Neg); + assert_that!(msg.has_optional_nested_enum(), eq(true)); assert_that!(msg.optional_nested_enum_opt(), eq(Optional::Set(NestedEnum::Neg))); assert_that!(msg.optional_nested_enum(), eq(NestedEnum::Neg)); - msg.optional_nested_enum_mut().clear(); + msg.clear_optional_nested_enum(); + assert_that!(msg.has_optional_nested_enum(), eq(false)); assert_that!(msg.optional_nested_enum_opt(), eq(Optional::Unset(NestedEnum::Foo))); assert_that!(msg.optional_nested_enum(), eq(NestedEnum::Foo)); } #[test] fn test_default_nested_enum_accessors() { - use TestAllTypes_::NestedEnum; + use test_all_types::NestedEnum; let mut msg = TestAllTypes::new(); assert_that!(msg.default_nested_enum(), eq(NestedEnum::Bar)); - assert_that!(msg.default_nested_enum_mut().get(), eq(NestedEnum::Bar)); - assert_that!(msg.default_nested_enum_mut().is_set(), eq(false)); assert_that!(msg.default_nested_enum_opt(), eq(Optional::Unset(NestedEnum::Bar))); - msg.default_nested_enum_mut().set(NestedEnum::Baz); + msg.set_default_nested_enum(NestedEnum::Baz); assert_that!(msg.default_nested_enum(), eq(NestedEnum::Baz)); - assert_that!(msg.default_nested_enum_mut().get(), eq(NestedEnum::Baz)); - assert_that!(msg.default_nested_enum_mut().is_set(), eq(true)); assert_that!(msg.default_nested_enum_opt(), eq(Optional::Set(NestedEnum::Baz))); - msg.default_nested_enum_mut().clear(); + msg.clear_default_nested_enum(); assert_that!(msg.default_nested_enum(), eq(NestedEnum::Bar)); - assert_that!(msg.default_nested_enum_mut().get(), eq(NestedEnum::Bar)); - assert_that!(msg.default_nested_enum_mut().is_set(), eq(false)); assert_that!(msg.default_nested_enum_opt(), eq(Optional::Unset(NestedEnum::Bar))); - - msg.default_nested_enum_mut().or_default(); - assert_that!(msg.default_nested_enum(), eq(NestedEnum::Bar)); - assert_that!(msg.default_nested_enum_mut().get(), eq(NestedEnum::Bar)); - assert_that!(msg.default_nested_enum_mut().is_set(), eq(true)); - assert_that!(msg.default_nested_enum_opt(), eq(Optional::Set(NestedEnum::Bar))); } #[test] @@ -837,11 +619,11 @@ fn test_optional_foreign_enum_accessors() { assert_that!(msg.optional_foreign_enum_opt(), eq(Optional::Unset(ForeignEnum::ForeignFoo))); assert_that!(msg.optional_foreign_enum(), eq(ForeignEnum::ForeignFoo)); - msg.optional_foreign_enum_mut().set(ForeignEnum::ForeignBax); + msg.set_optional_foreign_enum(ForeignEnum::ForeignBax); assert_that!(msg.optional_foreign_enum_opt(), eq(Optional::Set(ForeignEnum::ForeignBax))); assert_that!(msg.optional_foreign_enum(), eq(ForeignEnum::ForeignBax)); - msg.optional_foreign_enum_mut().clear(); + msg.clear_optional_foreign_enum(); assert_that!(msg.optional_foreign_enum_opt(), eq(Optional::Unset(ForeignEnum::ForeignFoo))); assert_that!(msg.optional_foreign_enum(), eq(ForeignEnum::ForeignFoo)); } @@ -852,27 +634,15 @@ fn test_default_foreign_enum_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_foreign_enum(), eq(ForeignEnum::ForeignBar)); - assert_that!(msg.default_foreign_enum_mut().get(), eq(ForeignEnum::ForeignBar)); - assert_that!(msg.default_foreign_enum_mut().is_set(), eq(false)); assert_that!(msg.default_foreign_enum_opt(), eq(Optional::Unset(ForeignEnum::ForeignBar))); - msg.default_foreign_enum_mut().set(ForeignEnum::ForeignBaz); + msg.set_default_foreign_enum(ForeignEnum::ForeignBaz); assert_that!(msg.default_foreign_enum(), eq(ForeignEnum::ForeignBaz)); - assert_that!(msg.default_foreign_enum_mut().get(), eq(ForeignEnum::ForeignBaz)); - assert_that!(msg.default_foreign_enum_mut().is_set(), eq(true)); assert_that!(msg.default_foreign_enum_opt(), eq(Optional::Set(ForeignEnum::ForeignBaz))); - msg.default_foreign_enum_mut().clear(); + msg.clear_default_foreign_enum(); assert_that!(msg.default_foreign_enum(), eq(ForeignEnum::ForeignBar)); - assert_that!(msg.default_foreign_enum_mut().get(), eq(ForeignEnum::ForeignBar)); - assert_that!(msg.default_foreign_enum_mut().is_set(), eq(false)); assert_that!(msg.default_foreign_enum_opt(), eq(Optional::Unset(ForeignEnum::ForeignBar))); - - msg.default_foreign_enum_mut().or_default(); - assert_that!(msg.default_foreign_enum(), eq(ForeignEnum::ForeignBar)); - assert_that!(msg.default_foreign_enum_mut().get(), eq(ForeignEnum::ForeignBar)); - assert_that!(msg.default_foreign_enum_mut().is_set(), eq(true)); - assert_that!(msg.default_foreign_enum_opt(), eq(Optional::Set(ForeignEnum::ForeignBar))); } #[test] @@ -883,11 +653,11 @@ fn test_optional_import_enum_accessors() { assert_that!(msg.optional_import_enum_opt(), eq(Optional::Unset(ImportEnum::ImportFoo))); assert_that!(msg.optional_import_enum(), eq(ImportEnum::ImportFoo)); - msg.optional_import_enum_mut().set(ImportEnum::ImportBar); + msg.set_optional_import_enum(ImportEnum::ImportBar); assert_that!(msg.optional_import_enum_opt(), eq(Optional::Set(ImportEnum::ImportBar))); assert_that!(msg.optional_import_enum(), eq(ImportEnum::ImportBar)); - msg.optional_import_enum_mut().clear(); + msg.clear_optional_import_enum(); assert_that!(msg.optional_import_enum_opt(), eq(Optional::Unset(ImportEnum::ImportFoo))); assert_that!(msg.optional_import_enum(), eq(ImportEnum::ImportFoo)); } @@ -898,207 +668,106 @@ fn test_default_import_enum_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_import_enum(), eq(ImportEnum::ImportBar)); - assert_that!(msg.default_import_enum_mut().get(), eq(ImportEnum::ImportBar)); - assert_that!(msg.default_import_enum_mut().is_set(), eq(false)); assert_that!(msg.default_import_enum_opt(), eq(Optional::Unset(ImportEnum::ImportBar))); - msg.default_import_enum_mut().set(ImportEnum::ImportBaz); + msg.set_default_import_enum(ImportEnum::ImportBaz); assert_that!(msg.default_import_enum(), eq(ImportEnum::ImportBaz)); - assert_that!(msg.default_import_enum_mut().get(), eq(ImportEnum::ImportBaz)); - assert_that!(msg.default_import_enum_mut().is_set(), eq(true)); assert_that!(msg.default_import_enum_opt(), eq(Optional::Set(ImportEnum::ImportBaz))); - msg.default_import_enum_mut().clear(); + msg.clear_default_import_enum(); assert_that!(msg.default_import_enum(), eq(ImportEnum::ImportBar)); - assert_that!(msg.default_import_enum_mut().get(), eq(ImportEnum::ImportBar)); - assert_that!(msg.default_import_enum_mut().is_set(), eq(false)); assert_that!(msg.default_import_enum_opt(), eq(Optional::Unset(ImportEnum::ImportBar))); - - msg.default_import_enum_mut().or_default(); - assert_that!(msg.default_import_enum(), eq(ImportEnum::ImportBar)); - assert_that!(msg.default_import_enum_mut().get(), eq(ImportEnum::ImportBar)); - assert_that!(msg.default_import_enum_mut().is_set(), eq(true)); - assert_that!(msg.default_import_enum_opt(), eq(Optional::Set(ImportEnum::ImportBar))); } #[test] fn test_oneof_accessors() { + use unittest_proto::test_oneof2::{Foo::*, FooCase, NestedEnum}; use unittest_proto::TestOneof2; - use unittest_proto::TestOneof2_::{Foo::*, NestedEnum}; let mut msg = TestOneof2::new(); assert_that!(msg.foo(), matches_pattern!(not_set(_))); + assert_that!(msg.foo_case(), eq(FooCase::not_set)); - msg.foo_int_mut().set(7); + msg.set_foo_int(7); + assert_that!(msg.has_foo_int(), eq(true)); assert_that!(msg.foo_int_opt(), eq(Optional::Set(7))); assert_that!(msg.foo(), matches_pattern!(FooInt(eq(7)))); + assert_that!(msg.foo_case(), eq(FooCase::FooInt)); - msg.foo_int_mut().clear(); + msg.clear_foo_int(); + assert_that!(msg.has_foo_int(), eq(false)); assert_that!(msg.foo_int_opt(), eq(Optional::Unset(0))); assert_that!(msg.foo(), matches_pattern!(not_set(_))); + assert_that!(msg.foo_case(), eq(FooCase::not_set)); - msg.foo_int_mut().set(7); - msg.foo_bytes_mut().set(b"123"); + msg.set_foo_int(7); + msg.set_foo_bytes(b"123"); + assert_that!(msg.has_foo_int(), eq(false)); assert_that!(msg.foo_int_opt(), eq(Optional::Unset(0))); assert_that!(msg.foo(), matches_pattern!(FooBytes(eq(b"123")))); + assert_that!(msg.foo_case(), eq(FooCase::FooBytes)); - msg.foo_enum_mut().set(NestedEnum::Foo); + msg.set_foo_enum(NestedEnum::Foo); assert_that!(msg.foo(), matches_pattern!(FooEnum(eq(NestedEnum::Foo)))); + assert_that!(msg.foo_case(), eq(FooCase::FooEnum)); // Test the accessors or $Msg$Mut let mut msg_mut = msg.as_mut(); assert_that!(msg_mut.foo(), matches_pattern!(FooEnum(eq(NestedEnum::Foo)))); - msg_mut.foo_int_mut().set(7); - msg_mut.foo_bytes_mut().set(b"123"); + msg_mut.set_foo_int(7); + msg_mut.set_foo_bytes(b"123"); assert_that!(msg_mut.foo(), matches_pattern!(FooBytes(eq(b"123")))); + assert_that!(msg_mut.foo_case(), eq(FooCase::FooBytes)); assert_that!(msg_mut.foo_int_opt(), eq(Optional::Unset(0))); // Test the accessors on $Msg$View let msg_view = msg.as_view(); assert_that!(msg_view.foo(), matches_pattern!(FooBytes(eq(b"123")))); + assert_that!(msg_view.foo_case(), eq(FooCase::FooBytes)); assert_that!(msg_view.foo_int_opt(), eq(Optional::Unset(0))); // TODO: Add tests covering a message-type field in a oneof. } -#[test] -fn test_oneof_mut_accessors() { - use unittest_proto::TestOneof2; - use unittest_proto::TestOneof2_::{Foo, FooMut::*, NestedEnum}; - - let mut msg = TestOneof2::new(); - assert_that!(msg.foo_mut(), matches_pattern!(not_set(_))); - - msg.foo_int_mut().set(7); - - match msg.foo_mut() { - FooInt(mut v) => { - assert_that!(v.get(), eq(7)); - v.set(8); - assert_that!(v.get(), eq(8)); - } - f => panic!("unexpected field_mut type! {:?}", f), - } - - // Confirm that the mut write above applies to both the field accessor and the - // oneof view accessor. - assert_that!(msg.foo_int_opt(), eq(Optional::Set(8))); - assert_that!(msg.foo(), matches_pattern!(Foo::FooInt(_))); - - msg.foo_int_mut().clear(); - assert_that!(msg.foo_mut(), matches_pattern!(not_set(_))); - - msg.foo_int_mut().set(7); - msg.foo_bytes_mut().set(b"123"); - assert_that!(msg.foo_mut(), matches_pattern!(FooBytes(_))); - - msg.foo_enum_mut().set(NestedEnum::Baz); - assert_that!(msg.foo_mut(), matches_pattern!(FooEnum(_))); - - // Test the mut accessors or $Msg$Mut - let mut msg_mut = msg.as_mut(); - match msg_mut.foo_mut() { - FooEnum(mut v) => { - assert_that!(v.get(), eq(NestedEnum::Baz)); - v.set(NestedEnum::Bar); - assert_that!(v.get(), eq(NestedEnum::Bar)); - } - f => panic!("unexpected field_mut type! {:?}", f), - } - assert_that!(msg.foo_enum(), eq(NestedEnum::Bar)); - - // TODO: Add tests covering a message-type field in a oneof. -} - #[test] fn test_msg_oneof_default_accessors() { - use unittest_proto::TestOneof2_::{Bar::*, NestedEnum}; + use unittest_proto::test_oneof2::{Bar::*, BarCase, NestedEnum}; let mut msg = unittest_proto::TestOneof2::new(); assert_that!(msg.bar(), matches_pattern!(not_set(_))); - msg.bar_int_mut().set(7); + msg.set_bar_int(7); assert_that!(msg.bar_int_opt(), eq(Optional::Set(7))); assert_that!(msg.bar(), matches_pattern!(BarInt(eq(7)))); + assert_that!(msg.bar_case(), eq(BarCase::BarInt)); - msg.bar_int_mut().clear(); + msg.clear_bar_int(); assert_that!(msg.bar_int_opt(), eq(Optional::Unset(5))); assert_that!(msg.bar(), matches_pattern!(not_set(_))); + assert_that!(msg.bar_case(), eq(BarCase::not_set)); - msg.bar_int_mut().set(7); - msg.bar_bytes_mut().set(b"123"); + msg.set_bar_int(7); + msg.set_bar_bytes(b"123"); assert_that!(msg.bar_int_opt(), eq(Optional::Unset(5))); assert_that!(msg.bar_enum_opt(), eq(Optional::Unset(NestedEnum::Bar))); assert_that!(msg.bar(), matches_pattern!(BarBytes(eq(b"123")))); + assert_that!(msg.bar_case(), eq(BarCase::BarBytes)); - msg.bar_enum_mut().set(NestedEnum::Baz); + msg.set_bar_enum(NestedEnum::Baz); assert_that!(msg.bar(), matches_pattern!(BarEnum(eq(NestedEnum::Baz)))); + assert_that!(msg.bar_case(), eq(BarCase::BarEnum)); assert_that!(msg.bar_int_opt(), eq(Optional::Unset(5))); // TODO: Add tests covering a message-type field in a oneof. } -#[test] -fn test_oneof_default_mut_accessors() { - use unittest_proto::TestOneof2_::{Bar, BarMut, BarMut::*, NestedEnum}; - - let mut msg = unittest_proto::TestOneof2::new(); - assert_that!(msg.bar_mut(), matches_pattern!(not_set(_))); - - msg.bar_int_mut().set(7); - - match msg.bar_mut() { - BarInt(mut v) => { - assert_that!(v.get(), eq(7)); - v.set(8); - assert_that!(v.get(), eq(8)); - } - f => panic!("unexpected field_mut type! {:?}", f), - } - - // Confirm that the mut write above applies to all three of: - // - The field accessor - // - The oneof mut accessor - // - The oneof view accessor - // And then each of the applicable cases on: - // - The owned msg directly - // - The msg as a $Msg$Mut - // - The msg as a $Msg$View - assert_that!(msg.bar_int_opt(), eq(Optional::Set(8))); - assert_that!(msg.bar_mut(), matches_pattern!(BarMut::BarInt(_))); - assert_that!(msg.bar(), matches_pattern!(Bar::BarInt(_))); - - let mut msg_mut = msg.as_mut(); - assert_that!(msg_mut.bar_int_opt(), eq(Optional::Set(8))); - assert_that!(msg_mut.bar_mut(), matches_pattern!(BarMut::BarInt(_))); - assert_that!(msg_mut.bar(), matches_pattern!(Bar::BarInt(_))); - - let msg_view = msg.as_view(); - assert_that!(msg_view.bar_int_opt(), eq(Optional::Set(8))); - // This test correctly fails to compile if this line is uncommented: - // assert_that!(msg_view.bar_mut(), matches_pattern!(BarMut::BarInt(_))); - assert_that!(msg_view.bar(), matches_pattern!(Bar::BarInt(_))); - - msg.bar_int_mut().clear(); - assert_that!(msg.bar_mut(), matches_pattern!(not_set(_))); - - msg.bar_int_mut().set(7); - msg.bar_bytes_mut().set(b"123"); - assert_that!(msg.bar_mut(), matches_pattern!(BarBytes(_))); - - msg.bar_enum_mut().set(NestedEnum::Baz); - assert_that!(msg.bar_mut(), matches_pattern!(BarEnum(_))); - - // TODO: Add tests covering a message-type field in a oneof. -} - #[test] fn test_set_message_from_view() { use protobuf::MutProxy; let mut m1 = TestAllTypes::new(); - m1.optional_int32_mut().set(1); + m1.set_optional_int32(1); let mut m2 = TestAllTypes::new(); m2.as_mut().set(m1.as_view()); @@ -1113,14 +782,14 @@ fn test_group() { assert_that!(m.optionalgroup_opt().is_set(), eq(false)); assert_that!(m.optionalgroup().a(), eq(0)); - m.optionalgroup_mut().or_default().a_mut().set(7); + m.optionalgroup_mut().set_a(7); assert_that!(m.optionalgroup_opt().is_set(), eq(true)); assert_that!(m.optionalgroup().a(), eq(7)); } #[test] fn test_submsg_setter() { - use TestAllTypes_::*; + use test_all_types::*; let mut nested = NestedMessage::new(); nested.set_bb(7); diff --git a/rust/test/shared/edition2023_test.rs b/rust/test/shared/edition2023_test.rs index 35388df237..44f10bee2a 100644 --- a/rust/test/shared/edition2023_test.rs +++ b/rust/test/shared/edition2023_test.rs @@ -13,11 +13,7 @@ use googletest::prelude::*; #[test] fn check_edition2023_works() { - let mut msg = edition2023_proto::EditionsMessage::new(); - - // plain_field supports presence. - assert_that!(msg.plain_field_mut().or_default().get(), eq(0)); - - // implicit presence fields' _mut() skips FieldEntry. - assert_that!(msg.implicit_presence_field_mut().get(), eq(0)); + let msg = edition2023_proto::EditionsMessage::new(); + assert_that!(msg.plain_field_opt().into_inner(), eq(0)); + assert_that!(msg.implicit_presence_field(), eq(0)); } diff --git a/rust/test/shared/enum_test.rs b/rust/test/shared/enum_test.rs index 6fe44100fe..c11a4906c0 100644 --- a/rust/test/shared/enum_test.rs +++ b/rust/test/shared/enum_test.rs @@ -13,17 +13,17 @@ use unittest_proto::*; #[test] fn test_nested_enum_values() { - assert_that!(i32::from(TestAllTypes_::NestedEnum::Foo), eq(1)); - assert_that!(i32::from(TestAllTypes_::NestedEnum::Bar), eq(2)); - assert_that!(i32::from(TestAllTypes_::NestedEnum::Baz), eq(3)); - assert_that!(i32::from(TestAllTypes_::NestedEnum::Neg), eq(-1)); + assert_that!(i32::from(test_all_types::NestedEnum::Foo), eq(1)); + assert_that!(i32::from(test_all_types::NestedEnum::Bar), eq(2)); + assert_that!(i32::from(test_all_types::NestedEnum::Baz), eq(3)); + assert_that!(i32::from(test_all_types::NestedEnum::Neg), eq(-1)); } #[test] fn test_isolated_nested_enum() { // Ensure that the enum is generated even when it's the only nested type for the // message. - assert_that!(i32::from(TestRequiredEnumNoMask_::NestedEnum::Foo), eq(2)); + assert_that!(i32::from(test_required_enum_no_mask::NestedEnum::Foo), eq(2)); } #[test] @@ -40,7 +40,7 @@ fn test_enum_defaults() { TestEnumWithDuplicateStrippedPrefixNames::default(), eq(TestEnumWithDuplicateStrippedPrefixNames::Unknown) ); - assert_that!(TestAllTypes_::NestedEnum::default(), eq(TestAllTypes_::NestedEnum::Foo)); + assert_that!(test_all_types::NestedEnum::default(), eq(test_all_types::NestedEnum::Foo)); } #[test] diff --git a/rust/test/shared/fields_with_imported_types_test.rs b/rust/test/shared/fields_with_imported_types_test.rs index c0651a61b9..c3bab55f3a 100644 --- a/rust/test/shared/fields_with_imported_types_test.rs +++ b/rust/test/shared/fields_with_imported_types_test.rs @@ -30,8 +30,8 @@ fn test_enum_field_generated() { #[test] fn test_oneof_message_field_generated() { + use fields_with_imported_types_proto::msg_with_fields_with_imported_types::ImportedTypesOneof::not_set; use fields_with_imported_types_proto::MsgWithFieldsWithImportedTypes; - use fields_with_imported_types_proto::MsgWithFieldsWithImportedTypes_::ImportedTypesOneof::not_set; use imported_types_proto::ImportedEnum; use imported_types_proto::ImportedMessageView; diff --git a/rust/test/shared/nested_types_test.rs b/rust/test/shared/nested_types_test.rs index b149e574d9..6698d90a9c 100644 --- a/rust/test/shared/nested_types_test.rs +++ b/rust/test/shared/nested_types_test.rs @@ -10,14 +10,14 @@ #[test] fn test_nested_messages_accessible() { let _parent: unittest_proto::TestAllTypes; - let _child: unittest_proto::TestAllTypes_::NestedMessage; - unittest_proto::TestChildExtensionData_:: - NestedTestAllExtensionsData_::NestedDynamicExtensions::new(); + let _child: unittest_proto::test_all_types::NestedMessage; + unittest_proto::test_child_extension_data:: + nested_test_all_extensions_data::NestedDynamicExtensions::new(); } #[test] fn test_nested_enums_accessible() { let _parent: unittest_proto::TestAllTypes; - let _child: unittest_proto::TestAllTypes_::NestedEnum; - unittest_proto::TestDynamicExtensions_::DynamicEnumType::default(); + let _child: unittest_proto::test_all_types::NestedEnum; + unittest_proto::test_dynamic_extensions::DynamicEnumType::default(); } diff --git a/rust/test/shared/reserved_test.rs b/rust/test/shared/reserved_test.rs index cbfcdc84ca..0d2cb52bb6 100644 --- a/rust/test/shared/reserved_test.rs +++ b/rust/test/shared/reserved_test.rs @@ -7,8 +7,8 @@ /// Test covering proto compilation with reserved words. use googletest::prelude::*; -use reserved_proto::r#enum; use reserved_proto::Self__mangled_because_ident_isnt_a_legal_raw_identifier; +use reserved_proto::{r#enum, Ref}; #[test] fn test_reserved_keyword_in_accessors() { @@ -19,6 +19,6 @@ fn test_reserved_keyword_in_accessors() { #[test] fn test_reserved_keyword_in_messages() { - let msg = r#enum::new(); - let _ = msg.r#const(); + let _ = r#enum::new(); + let _ = Ref::new().r#const(); } diff --git a/rust/test/shared/simple_nested_test.rs b/rust/test/shared/simple_nested_test.rs index a5dd862557..73c4e00785 100644 --- a/rust/test/shared/simple_nested_test.rs +++ b/rust/test/shared/simple_nested_test.rs @@ -6,35 +6,34 @@ // https://developers.google.com/open-source/licenses/bsd use googletest::prelude::*; -use nested_proto::Outer_::InnerMut; -use nested_proto::Outer_::InnerView; -use nested_proto::Outer_::Inner_::InnerEnum; +use nested_proto::outer::inner::InnerEnum; +use nested_proto::outer::InnerView; use nested_proto::*; #[test] fn test_deeply_nested_message() { let deep = - Outer_::Inner_::SuperInner_::DuperInner_::EvenMoreInner_::CantBelieveItsSoInner::new(); + outer::inner::super_inner::duper_inner::even_more_inner::CantBelieveItsSoInner::new(); assert_that!(deep.num(), eq(0)); - let outer_msg = Outer::new(); - assert_that!(outer_msg.deep().num(), eq(0)); + let outermsg = Outer::new(); + assert_that!(outermsg.deep().num(), eq(0)); } #[test] fn test_deeply_nested_enum() { - use Outer_::Inner_::SuperInner_::DuperInner_::EvenMoreInner_::JustWayTooInner; + use outer::inner::super_inner::duper_inner::even_more_inner::JustWayTooInner; let deep = JustWayTooInner::default(); assert_that!(i32::from(deep), eq(0)); - let outer_msg = Outer::new(); - assert_that!(outer_msg.deep_enum(), eq(JustWayTooInner::Unspecified)); + let outermsg = Outer::new(); + assert_that!(outermsg.deep_enum(), eq(JustWayTooInner::Unspecified)); } #[test] fn test_nested_views() { - let outer_msg = Outer::new(); - let inner_msg: InnerView<'_> = outer_msg.inner(); + let outermsg = Outer::new(); + let inner_msg: InnerView<'_> = outermsg.inner(); assert_that!(inner_msg.double(), eq(0.0)); assert_that!(inner_msg.float(), eq(0.0)); assert_that!(inner_msg.int32(), eq(0)); @@ -59,87 +58,27 @@ fn test_nested_view_lifetimes() { // Ensure that views have the lifetime of the first layer of borrow, and don't // create intermediate borrows through nested accessors. - let outer_msg = Outer::new(); + let outermsg = Outer::new(); - let string = outer_msg.inner().string(); + let string = outermsg.inner().string(); assert_that!(string, eq("")); - let bytes = outer_msg.inner().bytes(); + let bytes = outermsg.inner().bytes(); assert_that!(bytes, eq(b"")); - let inner_submsg = outer_msg.inner().inner_submsg(); + let inner_submsg = outermsg.inner().inner_submsg(); assert_that!(inner_submsg.flag(), eq(false)); - let repeated_int32 = outer_msg.inner().repeated_int32(); + let repeated_int32 = outermsg.inner().repeated_int32(); assert_that!(repeated_int32, empty()); - let repeated_inner_submsg = outer_msg.inner().repeated_inner_submsg(); + let repeated_inner_submsg = outermsg.inner().repeated_inner_submsg(); assert_that!(repeated_inner_submsg, empty()); - let string_map = outer_msg.inner().string_map(); + let string_map = outermsg.inner().string_map(); assert_that!(string_map.len(), eq(0)); } -#[test] -fn test_nested_muts() { - // Covers the setting of a mut and the following assertion - // confirming the new value. Replacement example: - // old: - // inner_msg.double_mut().set(543.21); - // assert_that!(inner_msg.double_mut().get(), eq(543.21)); - // new: - // set_and_test_mut!(inner_msg => double_mut, 543.21); - macro_rules! set_and_test_mut { - ( $a:expr => $($target_mut:ident, $val:expr;)* ) => { - $( - $a.$target_mut().set($val); - assert_that!($a.$target_mut().get(), eq($val)); - )* - }; - } - - let mut outer_msg = Outer::new(); - let mut inner_msg: InnerMut<'_> = outer_msg.inner_mut().or_default(); - assert_that!( - inner_msg, - matches_pattern!(InnerMut{ - float(): eq(0.0), - double(): eq(0.0), - int32(): eq(0), - int64(): eq(0), - uint32(): eq(0), - uint64(): eq(0), - sint32(): eq(0), - sint64(): eq(0), - fixed32(): eq(0), - fixed64(): eq(0), - sfixed32(): eq(0), - sfixed64(): eq(0), - bool(): eq(false), - inner_enum(): eq(InnerEnum::Unspecified) - }) - ); - assert_that!(inner_msg.string_mut().get(), eq("")); - assert_that!(inner_msg.bytes_mut().get(), eq(b"")); - - set_and_test_mut!(inner_msg => - double_mut, 543.21; - float_mut, 1.23; - int32_mut, 12; - int64_mut, 42; - uint32_mut, 13; - uint64_mut, 5000; - sint32_mut, -2; - sint64_mut, 322; - fixed32_mut, 77; - fixed64_mut, 999; - bool_mut, true; - string_mut, "hi"; - bytes_mut, b"bye"; - inner_enum_mut, InnerEnum::Foo; - ); -} - #[test] fn test_msg_from_outside() { // let's make sure that we're not just working for messages nested inside @@ -164,12 +103,12 @@ fn test_recursive_view() { #[test] fn test_recursive_mut() { let mut rec = nested_proto::Recursive::new(); - let mut one = rec.rec_mut().or_default(); - let mut two = one.rec_mut().or_default(); - let mut three = two.rec_mut().or_default(); - let mut four = three.rec_mut().or_default(); + let mut one = rec.rec_mut(); + let mut two = one.rec_mut(); + let mut three = two.rec_mut(); + let mut four = three.rec_mut(); - four.num_mut().set(1); + four.set_num(1); assert_that!(four.num(), eq(1)); assert_that!(rec.num(), eq(0)); diff --git a/src/file_lists.cmake b/src/file_lists.cmake index 2ff82de2dd..a86a2c877e 100644 --- a/src/file_lists.cmake +++ b/src/file_lists.cmake @@ -304,6 +304,7 @@ set(libprotoc_srcs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/file.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/generator.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/helpers.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/ifndef_guard.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/padding_optimizer.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/parse_function_generator.cc @@ -420,6 +421,7 @@ set(libprotoc_hdrs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/file.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/generator.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/helpers.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/ifndef_guard.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message_layout_helper.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/names.h @@ -595,6 +597,7 @@ set(libupb_hdrs ${protobuf_SOURCE_DIR}/upb/base/status.hpp ${protobuf_SOURCE_DIR}/upb/base/string_view.h ${protobuf_SOURCE_DIR}/upb/base/upcast.h + ${protobuf_SOURCE_DIR}/upb/generated_code_support.h ${protobuf_SOURCE_DIR}/upb/hash/common.h ${protobuf_SOURCE_DIR}/upb/hash/int_table.h ${protobuf_SOURCE_DIR}/upb/hash/str_table.h @@ -1092,6 +1095,7 @@ set(compiler_test_files ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/copy_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/file_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/generator_unittest.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/ifndef_guard_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message_size_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/metadata_test.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/move_unittest.cc diff --git a/src/google/protobuf/BUILD.bazel b/src/google/protobuf/BUILD.bazel index a1c9c0b5b7..0786eae48a 100644 --- a/src/google/protobuf/BUILD.bazel +++ b/src/google/protobuf/BUILD.bazel @@ -333,6 +333,7 @@ cc_library( deps = [ "//src/google/protobuf:port", "//src/google/protobuf/stubs:lite", + "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/log:absl_log", "@com_google_absl//absl/numeric:bits", @@ -1669,6 +1670,7 @@ cc_test( "//src/google/protobuf/stubs", "//src/google/protobuf/testing", "//src/google/protobuf/testing:file", + "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc index 24efc52afc..ba4ede8a9f 100644 --- a/src/google/protobuf/any.pb.cc +++ b/src/google/protobuf/any.pb.cc @@ -6,6 +6,7 @@ #include "google/protobuf/any.pb.h" #include +#include #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" @@ -181,6 +182,7 @@ Any::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Any, _impl_._cached_size_), false, @@ -358,8 +360,8 @@ namespace protobuf { #if defined(__llvm__) #pragma clang diagnostic pop #endif // __llvm__ -PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 -static ::std::false_type _static_init_ PROTOBUF_UNUSED = - (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fany_2eproto), - ::std::false_type{}); +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ PROTOBUF_UNUSED = + (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fany_2eproto), + ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc index f6b3dab98f..dfe778b7d3 100644 --- a/src/google/protobuf/api.pb.cc +++ b/src/google/protobuf/api.pb.cc @@ -6,6 +6,7 @@ #include "google/protobuf/api.pb.h" #include +#include #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" @@ -311,6 +312,7 @@ Api::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Api, _impl_._cached_size_), false, @@ -709,6 +711,7 @@ Method::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Method, _impl_._cached_size_), false, @@ -1061,6 +1064,7 @@ Mixin::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Mixin, _impl_._cached_size_), false, @@ -1238,8 +1242,8 @@ namespace protobuf { } // namespace protobuf } // namespace google // @@protoc_insertion_point(global_scope) -PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 -static ::std::false_type _static_init_ PROTOBUF_UNUSED = - (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fapi_2eproto), - ::std::false_type{}); +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ PROTOBUF_UNUSED = + (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fapi_2eproto), + ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/arena_align.h b/src/google/protobuf/arena_align.h index d3d2d767e6..b9c9447d7c 100644 --- a/src/google/protobuf/arena_align.h +++ b/src/google/protobuf/arena_align.h @@ -55,6 +55,7 @@ #include #include +#include "google/protobuf/stubs/common.h" #include "absl/log/absl_check.h" #include "absl/numeric/bits.h" diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc index 7e2f0ad75a..8c961b4dd9 100644 --- a/src/google/protobuf/arena_unittest.cc +++ b/src/google/protobuf/arena_unittest.cc @@ -7,13 +7,17 @@ #include "google/protobuf/arena.h" +#include + #include #include #include #include #include +#include #include #include +#include // IWYU pragma: keep for operator new #include #include #include @@ -874,7 +878,7 @@ TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) { const Reflection* r = arena_message->GetReflection(); const FieldDescriptor* f = arena_message->GetDescriptor()->FindFieldByName( "optional_nested_message"); - nested_msg = static_cast( + nested_msg = DownCastToGenerated( r->ReleaseMessage(arena_message, f)); } EXPECT_EQ(42, nested_msg->bb()); @@ -1482,7 +1486,7 @@ TEST(ArenaTest, MutableMessageReflection) { const Descriptor* d = message->GetDescriptor(); const FieldDescriptor* field = d->FindFieldByName("optional_nested_message"); TestAllTypes::NestedMessage* submessage = - static_cast( + DownCastToGenerated( r->MutableMessage(message, field)); TestAllTypes::NestedMessage* submessage_expected = message->mutable_optional_nested_message(); @@ -1492,7 +1496,7 @@ TEST(ArenaTest, MutableMessageReflection) { const FieldDescriptor* oneof_field = d->FindFieldByName("oneof_nested_message"); - submessage = static_cast( + submessage = DownCastToGenerated( r->MutableMessage(message, oneof_field)); submessage_expected = message->mutable_oneof_nested_message(); @@ -1655,7 +1659,7 @@ TEST(ArenaTest, Alignment) { Arena arena; for (int i = 0; i < 200; i++) { void* p = Arena::CreateArray(&arena, i); - ABSL_CHECK_EQ(reinterpret_cast(p) % 8, 0) << i << ": " << p; + ABSL_CHECK_EQ(reinterpret_cast(p) % 8, 0u) << i << ": " << p; } } diff --git a/src/google/protobuf/compiler/code_generator_unittest.cc b/src/google/protobuf/compiler/code_generator_unittest.cc index 5ad68126f0..f9ad1b37e2 100644 --- a/src/google/protobuf/compiler/code_generator_unittest.cc +++ b/src/google/protobuf/compiler/code_generator_unittest.cc @@ -120,15 +120,15 @@ TEST_F(CodeGeneratorTest, GetUnresolvedSourceFeaturesRoot) { option features.field_presence = EXPLICIT; // 2023 default option features.enum_type = CLOSED; // override - option features.(pb.test).int_file_feature = 8; - option features.(pb.test).string_source_feature = "file"; + option features.(pb.test).file_feature = VALUE5; + option features.(pb.test).source_feature = VALUE6; )schema"); ASSERT_THAT(file, NotNull()); EXPECT_THAT(TestGenerator::GetUnresolvedSourceFeatures(*file, pb::test), google::protobuf::EqualsProto(R"pb( - int_file_feature: 8 - string_source_feature: "file" + file_feature: VALUE5 + source_feature: VALUE6 )pb")); } @@ -142,15 +142,15 @@ TEST_F(CodeGeneratorTest, GetUnresolvedSourceFeaturesInherited) { import "google/protobuf/unittest_features.proto"; option features.enum_type = OPEN; - option features.(pb.test).int_file_feature = 6; + option features.(pb.test).file_feature = VALUE4; message EditionsMessage { - option features.(pb.test).int_message_feature = 7; - option features.(pb.test).int_multiple_feature = 8; + option features.(pb.test).message_feature = VALUE5; + option features.(pb.test).multiple_feature = VALUE6; string field = 1 [ features.field_presence = EXPLICIT, - features.(pb.test).int_multiple_feature = 9, - features.(pb.test).string_source_feature = "field" + features.(pb.test).multiple_feature = VALUE3, + features.(pb.test).source_feature = VALUE2 ]; } )schema"); @@ -162,8 +162,8 @@ TEST_F(CodeGeneratorTest, GetUnresolvedSourceFeaturesInherited) { EXPECT_THAT(TestGenerator::GetUnresolvedSourceFeatures(*field, pb::test), google::protobuf::EqualsProto(R"pb( - int_multiple_feature: 9 - string_source_feature: "field" + multiple_feature: VALUE3 + source_feature: VALUE2 )pb")); } @@ -182,8 +182,8 @@ TEST_F(CodeGeneratorTest, GetResolvedSourceFeaturesRoot) { option features.field_presence = EXPLICIT; // 2023 default option features.enum_type = CLOSED; // override - option features.(pb.test).int_file_feature = 8; - option features.(pb.test).string_source_feature = "file"; + option features.(pb.test).file_feature = VALUE6; + option features.(pb.test).source_feature = VALUE5; )schema"); ASSERT_THAT(file, NotNull()); @@ -195,9 +195,9 @@ TEST_F(CodeGeneratorTest, GetResolvedSourceFeaturesRoot) { EXPECT_EQ(features.field_presence(), FeatureSet::EXPLICIT); EXPECT_EQ(features.enum_type(), FeatureSet::CLOSED); - EXPECT_TRUE(ext.has_int_message_feature()); - EXPECT_EQ(ext.int_file_feature(), 8); - EXPECT_EQ(ext.string_source_feature(), "file"); + EXPECT_EQ(ext.file_feature(), pb::EnumFeature::VALUE6); + EXPECT_EQ(ext.source_feature(), pb::EnumFeature::VALUE5); + EXPECT_EQ(ext.field_feature(), pb::EnumFeature::VALUE1); } TEST_F(CodeGeneratorTest, GetResolvedSourceFeaturesInherited) { @@ -214,17 +214,17 @@ TEST_F(CodeGeneratorTest, GetResolvedSourceFeaturesInherited) { import "google/protobuf/unittest_features.proto"; option features.enum_type = CLOSED; - option features.(pb.test).int_source_feature = 5; - option features.(pb.test).int_file_feature = 6; + option features.(pb.test).source_feature = VALUE5; + option features.(pb.test).file_feature = VALUE6; message EditionsMessage { - option features.(pb.test).int_message_feature = 7; - option features.(pb.test).int_multiple_feature = 8; - option features.(pb.test).string_source_feature = "message"; + option features.(pb.test).message_feature = VALUE4; + option features.(pb.test).multiple_feature = VALUE3; + option features.(pb.test).source_feature2 = VALUE2; string field = 1 [ features.field_presence = IMPLICIT, - features.(pb.test).int_multiple_feature = 9, - features.(pb.test).string_source_feature = "field" + features.(pb.test).multiple_feature = VALUE5, + features.(pb.test).source_feature2 = VALUE3 ]; } )schema"); @@ -239,11 +239,11 @@ TEST_F(CodeGeneratorTest, GetResolvedSourceFeaturesInherited) { EXPECT_EQ(features.enum_type(), FeatureSet::CLOSED); EXPECT_EQ(features.field_presence(), FeatureSet::IMPLICIT); - EXPECT_EQ(ext.int_message_feature(), 7); - EXPECT_EQ(ext.int_file_feature(), 6); - EXPECT_EQ(ext.int_multiple_feature(), 9); - EXPECT_EQ(ext.int_source_feature(), 5); - EXPECT_EQ(ext.string_source_feature(), "field"); + EXPECT_EQ(ext.message_feature(), pb::EnumFeature::VALUE4); + EXPECT_EQ(ext.file_feature(), pb::EnumFeature::VALUE6); + EXPECT_EQ(ext.multiple_feature(), pb::EnumFeature::VALUE5); + EXPECT_EQ(ext.source_feature(), pb::EnumFeature::VALUE5); + EXPECT_EQ(ext.source_feature2(), pb::EnumFeature::VALUE3); } // TODO: Use the gtest versions once that's available in OSS. diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 84290eff06..f3bd0844e5 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -2657,14 +2657,6 @@ bool CommandLineInterface::GenerateOutput( return false; } - // TODO: Remove once Java lite supports editions. - if (output_directive.name == "--java_out" && experimental_editions_) { - if (!parameters.empty()) { - parameters.append(","); - } - parameters.append("experimental_editions"); - } - if (!output_directive.generator->GenerateAll(parsed_files, parameters, generator_context, &error)) { // Generator returned an error. diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 376f719009..7fb823365b 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -1713,8 +1713,8 @@ TEST_F(CommandLineInterfaceTest, Plugin_SourceFeatures) { package foo; message Foo { int32 b = 1 [ - features.(pb.test).int_field_feature = 99, - features.(pb.test).int_source_feature = 87 + features.(pb.test).field_feature = VALUE6, + features.(pb.test).source_feature = VALUE5 ]; } )schema"); @@ -1744,7 +1744,7 @@ TEST_F(CommandLineInterfaceTest, Plugin_SourceFeatures) { const FeatureSet& features = request.proto_file(2).message_type(0).field(0).options().features(); EXPECT_THAT(features, - EqualsProto(R"pb([pb.test] { int_field_feature: 99 })pb")); + EqualsProto(R"pb([pb.test] { field_feature: VALUE6 })pb")); } { @@ -1755,8 +1755,8 @@ TEST_F(CommandLineInterfaceTest, Plugin_SourceFeatures) { .options() .features(); EXPECT_THAT(features, EqualsProto(R"pb([pb.test] { - int_field_feature: 99 - int_source_feature: 87 + field_feature: VALUE6 + source_feature: VALUE5 })pb")); } } @@ -1965,20 +1965,20 @@ TEST_F(CommandLineInterfaceTest, EditionDefaultsWithExtension) { EXPECT_EQ(defaults.defaults(3).edition(), EDITION_99997_TEST_ONLY); EXPECT_EQ(defaults.defaults(4).edition(), EDITION_99998_TEST_ONLY); EXPECT_EQ( - defaults.defaults(0).features().GetExtension(pb::test).int_file_feature(), - -2); + defaults.defaults(0).features().GetExtension(pb::test).file_feature(), + pb::EnumFeature::VALUE1); EXPECT_EQ( - defaults.defaults(1).features().GetExtension(pb::test).int_file_feature(), - -3); + defaults.defaults(1).features().GetExtension(pb::test).file_feature(), + pb::EnumFeature::VALUE2); EXPECT_EQ( - defaults.defaults(2).features().GetExtension(pb::test).int_file_feature(), - 1); + defaults.defaults(2).features().GetExtension(pb::test).file_feature(), + pb::EnumFeature::VALUE3); EXPECT_EQ( - defaults.defaults(3).features().GetExtension(pb::test).int_file_feature(), - 2); + defaults.defaults(3).features().GetExtension(pb::test).file_feature(), + pb::EnumFeature::VALUE4); EXPECT_EQ( - defaults.defaults(4).features().GetExtension(pb::test).int_file_feature(), - 3); + defaults.defaults(4).features().GetExtension(pb::test).file_feature(), + pb::EnumFeature::VALUE5); } #ifndef _WIN32 diff --git a/src/google/protobuf/compiler/cpp/BUILD.bazel b/src/google/protobuf/compiler/cpp/BUILD.bazel index 8cbfa55113..c664a4bba0 100644 --- a/src/google/protobuf/compiler/cpp/BUILD.bazel +++ b/src/google/protobuf/compiler/cpp/BUILD.bazel @@ -69,6 +69,7 @@ cc_library( "field_generators/string_view_field.cc", "file.cc", "generator.cc", + "ifndef_guard.cc", "message.cc", "padding_optimizer.cc", "parse_function_generator.cc", @@ -82,6 +83,7 @@ cc_library( "field_generators/generators.h", "file.h", "generator.h", + "ifndef_guard.h", "message.h", "message_layout_helper.h", "padding_optimizer.h", @@ -115,6 +117,7 @@ cc_library( "@com_google_absl//absl/functional:any_invocable", "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/log:absl_log", + "@com_google_absl//absl/log:die_if_null", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", @@ -340,6 +343,22 @@ cc_test( ], ) +cc_test( + name = "ifndef_guard_unittest", + srcs = ["ifndef_guard_unittest.cc"], + deps = [ + ":cpp", + "//:protobuf", + "//src/google/protobuf/io", + "//src/google/protobuf/io:printer", + "@com_google_absl//absl/log:absl_check", + "@com_google_absl//absl/strings:string_view", + "@com_google_absl//absl/types:optional", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) + ################################################################################ # Distribution packaging ################################################################################ diff --git a/src/google/protobuf/compiler/cpp/extension.cc b/src/google/protobuf/compiler/cpp/extension.cc index 573bf4fbe4..41f33e2eba 100644 --- a/src/google/protobuf/compiler/cpp/extension.cc +++ b/src/google/protobuf/compiler/cpp/extension.cc @@ -14,6 +14,7 @@ #include #include +#include "absl/log/absl_check.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_replace.h" #include "google/protobuf/compiler/cpp/helpers.h" @@ -178,7 +179,16 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* p) { )cc"); } -void ExtensionGenerator::GenerateRegistration(io::Printer* p) { +bool ExtensionGenerator::WillGenerateRegistration(InitPriority priority) { + // We only use priority 101 for weak descriptors. + return priority != kInitPriority101 || + (descriptor_->cpp_type() == descriptor_->CPPTYPE_MESSAGE && + UsingImplicitWeakDescriptor(descriptor_->file(), options_)); +} + +void ExtensionGenerator::GenerateRegistration(io::Printer* p, + InitPriority priority) { + ABSL_CHECK(WillGenerateRegistration(priority)); auto vars = p->WithVars(variables_); switch (descriptor_->cpp_type()) { case FieldDescriptor::CPPTYPE_ENUM: @@ -205,10 +215,15 @@ void ExtensionGenerator::GenerateRegistration(io::Printer* p) { {"lazy", descriptor_->options().has_lazy() ? descriptor_->options().lazy() ? "kLazy" : "kEager" : "kUndefined"}}); - // Temporarily disable weak descriptor message for extensions. - // It is currently incorrect for custom descriptor options. We end up - // parsing the descriptors before the custom options are registered. - if (false && UsingImplicitWeakDescriptor(descriptor_->file(), options_)) { + const auto register_message = [&] { + p->Emit(R"cc( + ::_pbi::ExtensionSet::RegisterMessageExtension( + &$extendee$::default_instance(), $number$, $field_type$, + $repeated$, $packed$, &$message_type$::default_instance(), + $verify$, ::_pbi::LazyAnnotation::$lazy$), + )cc"); + }; + if (UsingImplicitWeakDescriptor(descriptor_->file(), options_)) { const auto find_index = [](auto* desc) { const std::vector msgs = FlattenMessagesInFile(desc->file()); @@ -224,23 +239,30 @@ void ExtensionGenerator::GenerateRegistration(io::Printer* p) { DescriptorTableName(descriptor_->message_type()->file(), options_)}, {"extension_index", find_index(descriptor_->message_type())}, + {"preregister", priority == kInitPriority101}, + {"fallback_for_opt_out", + // For now we have a fallback to use normal registration, + // which should only happen at priority 102. + // Once we turn this on by default we can remove the opt-in + // and the fallback. + [&] { + if (priority != kInitPriority102) return; + register_message(); + }}, }, R"cc( - ::_pbi::ExtensionSet::RegisterMessageExtension( - ::_pbi::GetPrototypeForWeakDescriptor(&$extendee_table$, - $extendee_index$), - $number$, $field_type$, $repeated$, $packed$, - ::_pbi::GetPrototypeForWeakDescriptor(&$extension_table$, - $extension_index$), - $verify$, ::_pbi::LazyAnnotation::$lazy$), + // +#if defined(PROTOBUF_INTERNAL_TEMPORARY_WEAK_EXTENSION_OPT_IN) + ::_pbi::ExtensionSet::RegisterWeakMessageExtension( + {&$extendee_table$, $extendee_index$}, $number$, $field_type$, + $repeated$, {&$extension_table$, $extension_index$}, $verify$, + ::_pbi::LazyAnnotation::$lazy$, $preregister$), +#else + $fallback_for_opt_out$, +#endif )cc"); } else { - p->Emit(R"cc( - ::_pbi::ExtensionSet::RegisterMessageExtension( - &$extendee$::default_instance(), $number$, $field_type$, - $repeated$, $packed$, &$message_type$::default_instance(), - $verify$, ::_pbi::LazyAnnotation::$lazy$), - )cc"); + register_message(); } break; } diff --git a/src/google/protobuf/compiler/cpp/extension.h b/src/google/protobuf/compiler/cpp/extension.h index 0558d65901..1365774dca 100644 --- a/src/google/protobuf/compiler/cpp/extension.h +++ b/src/google/protobuf/compiler/cpp/extension.h @@ -15,6 +15,7 @@ #include #include "absl/container/flat_hash_map.h" +#include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/cpp/options.h" #include "google/protobuf/port.h" @@ -56,7 +57,20 @@ class PROTOC_EXPORT ExtensionGenerator { // Source file stuff. void GenerateDefinition(io::Printer* p); - void GenerateRegistration(io::Printer* p); + // Extension registration can happen at different priority levels depending on + // the features used. + // + // For Weak Descriptor messages, we must use a two phase approach where we + // first register all the extensions that are fully linked in, and then we + // register the rest. To do that, we register the linked in extensions on + // priority 101 and the rest as priority 102. + // For extensions that are missing prototypes we need to create the prototypes + // before we can register them, but for that we need to successfully parse + // its descriptors, which might require other extensions to be registered + // first. All extensions required for descriptor parsing will be fully linked + // in and registered in the first phase. + void GenerateRegistration(io::Printer* p, InitPriority priority); + bool WillGenerateRegistration(InitPriority priority); bool IsScoped() const; diff --git a/src/google/protobuf/compiler/cpp/field_generators/message_field.cc b/src/google/protobuf/compiler/cpp/field_generators/message_field.cc index 8fe22a849f..e473681c5c 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/message_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/message_field.cc @@ -15,6 +15,7 @@ #include "absl/log/absl_check.h" #include "absl/memory/memory.h" +#include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/strings/substitute.h" #include "google/protobuf/compiler/cpp/field.h" @@ -595,7 +596,12 @@ void OneofMessage::GenerateClearingCode(io::Printer* p) const { p->Emit(R"cc( if (GetArena() == nullptr) { delete $field_$; - })cc"); + } else if ($pbi$::DebugHardenClearOneofMessageOnArena()) { + if ($field_$ != nullptr) { + $field_$->Clear(); + } + } + )cc"); } void OneofMessage::GenerateMessageClearingCode(io::Printer* p) const { diff --git a/src/google/protobuf/compiler/cpp/file.cc b/src/google/protobuf/compiler/cpp/file.cc index 9e7d9e58ed..d55c40d2bd 100644 --- a/src/google/protobuf/compiler/cpp/file.cc +++ b/src/google/protobuf/compiler/cpp/file.cc @@ -41,6 +41,7 @@ #include "google/protobuf/compiler/versions.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/dynamic_message.h" #include "google/protobuf/io/printer.h" // Must be last. @@ -480,6 +481,7 @@ void FileGenerator::GenerateSourceIncludes(io::Printer* p) { #include $h_include$ #include + #include )"); IncludeFile("third_party/protobuf/io/coded_stream.h", p); @@ -835,20 +837,26 @@ void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* p) { } void FileGenerator::GenerateStaticInitializer(io::Printer* p) { - if (static_initializers_.empty()) return; - p->Emit({{"expr", - [&] { - for (auto& init : static_initializers_) { - init(p); - } - }}}, - R"cc( - PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 - static ::std::false_type _static_init_ PROTOBUF_UNUSED = - ($expr$, ::std::false_type{}); - )cc"); - // Reset the vector because we might be generating many files. - static_initializers_.clear(); + int priority = 0; + for (auto& inits : static_initializers_) { + ++priority; + if (inits.empty()) continue; + p->Emit( + {{"priority", priority}, + {"expr", + [&] { + for (auto& init : inits) { + init(p); + } + }}}, + R"cc( + PROTOBUF_ATTRIBUTE_INIT_PRIORITY$priority$ static ::std::false_type + _static_init$priority$_ PROTOBUF_UNUSED = + ($expr$, ::std::false_type{}); + )cc"); + // Reset the vector because we might be generating many files. + inits.clear(); + } } void FileGenerator::GenerateSourceForExtension(int idx, io::Printer* p) { @@ -858,9 +866,13 @@ void FileGenerator::GenerateSourceForExtension(int idx, io::Printer* p) { NamespaceOpener ns(Namespace(file_, options_), p); extension_generators_[idx]->GenerateDefinition(p); - static_initializers_.push_back([this, idx](auto* p) { - extension_generators_[idx]->GenerateRegistration(p); - }); + for (auto priority : {kInitPriority101, kInitPriority102}) { + if (extension_generators_[idx]->WillGenerateRegistration(priority)) { + static_initializers_[priority].push_back([this, idx, priority](auto* p) { + extension_generators_[idx]->GenerateRegistration(p, priority); + }); + } + } GenerateStaticInitializer(p); } @@ -989,9 +1001,14 @@ void FileGenerator::GenerateSource(io::Printer* p) { for (int i = 0; i < extension_generators_.size(); ++i) { extension_generators_[i]->GenerateDefinition(p); if (!is_lazily_init) { - static_initializers_.push_back([&, i](auto* p) { - extension_generators_[i]->GenerateRegistration(p); - }); + for (auto priority : {kInitPriority101, kInitPriority102}) { + if (extension_generators_[i]->WillGenerateRegistration(priority)) { + static_initializers_[priority].push_back( + [this, i, priority](auto* p) { + extension_generators_[i]->GenerateRegistration(p, priority); + }); + } + } } } @@ -1020,9 +1037,69 @@ void FileGenerator::GenerateSource(io::Printer* p) { IncludeFile("third_party/protobuf/port_undef.inc", p); } +static void GatherAllCustomOptionTypes( + const FileDescriptor* file, + absl::btree_map& out) { + const DescriptorPool* pool = file->pool(); + const Descriptor* fd_proto_descriptor = pool->FindMessageTypeByName( + FileDescriptorProto::descriptor()->full_name()); + // Not all pools have descriptor.proto in them. In these cases there for sure + // are no custom options. + if (fd_proto_descriptor == nullptr) { + return; + } + + // It's easier to inspect file as a proto, because we can use reflection on + // the proto to iterate over all content. + // However, we can't use the generated proto linked into the proto compiler + // for this, since it doesn't know the extensions that are potentially present + // the protos that are being compiled. + // Use a dynamic one from the correct pool to parse them. + DynamicMessageFactory factory(pool); + std::unique_ptr fd_proto( + factory.GetPrototype(fd_proto_descriptor)->New()); + + { + FileDescriptorProto linkedin_fd_proto; + file->CopyTo(&linkedin_fd_proto); + ABSL_CHECK( + fd_proto->ParseFromString(linkedin_fd_proto.SerializeAsString())); + } + + // Now find all the messages used, recursively. + std::vector to_process = {fd_proto.get()}; + while (!to_process.empty()) { + const Message& msg = *to_process.back(); + to_process.pop_back(); + + std::vector fields; + const Reflection& reflection = *msg.GetReflection(); + reflection.ListFields(msg, &fields); + + for (auto* field : fields) { + const auto* field_msg = field->message_type(); + if (field_msg == nullptr) continue; + if (field->is_extension()) { + const Descriptor* desc = msg.GetDescriptor(); + out[desc->full_name()] = desc; + out[field_msg->full_name()] = field_msg; + } + if (field->is_repeated()) { + for (int i = 0; i < reflection.FieldSize(msg, field); i++) { + to_process.push_back(&reflection.GetRepeatedMessage(msg, field, i)); + } + } else { + to_process.push_back(&reflection.GetMessage(msg, field)); + } + } + } +} + static std::vector -GetMessagesToPinGloballyForWeakDescriptors(const FileDescriptor* file) { - std::vector out; +GetMessagesToPinGloballyForWeakDescriptors(const FileDescriptor* file, + const Options& options) { + // Sorted map to dedup and to make deterministic. + absl::btree_map res; // For simplicity we force pin request/response messages for all // services. The current implementation of services might not do @@ -1032,11 +1109,22 @@ GetMessagesToPinGloballyForWeakDescriptors(const FileDescriptor* file) { auto* service = file->service(i); for (int j = 0; j < service->method_count(); ++j) { auto* method = service->method(j); - out.push_back(method->input_type()); - out.push_back(method->output_type()); + res[method->input_type()->full_name()] = method->input_type(); + res[method->output_type()->full_name()] = method->output_type(); } } + // For correctness, we must ensure that all messages used as custom options in + // the descriptor are pinned. Otherwise, we can't properly parse the + // descriptor. + GatherAllCustomOptionTypes(file, res); + + std::vector out; + for (auto& p : res) { + // We don't need to pin the bootstrap types. It is wasteful. + if (IsBootstrapProto(options, p.second->file())) continue; + out.push_back(p.second); + } return out; } @@ -1266,8 +1354,10 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* p) { // Descriptor initialization will still be performed lazily when it's needed. if (!IsLazilyInitializedFile(file_->name())) { if (UsingImplicitWeakDescriptor(file_, options_)) { - for (auto* pinned : GetMessagesToPinGloballyForWeakDescriptors(file_)) { - static_initializers_.push_back([this, pinned](auto* p) { + for (auto* pinned : + GetMessagesToPinGloballyForWeakDescriptors(file_, options_)) { + static_initializers_[kInitPriority102].push_back([this, + pinned](auto* p) { p->Emit({{"pin", StrongReferenceToType(pinned, options_)}}, R"cc( $pin$, @@ -1275,7 +1365,7 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* p) { }); } } - static_initializers_.push_back([](auto* p) { + static_initializers_[kInitPriority102].push_back([](auto* p) { p->Emit(R"cc( ::_pbi::AddDescriptors(&$desc_table$), )cc"); diff --git a/src/google/protobuf/compiler/cpp/file.h b/src/google/protobuf/compiler/cpp/file.h index 8388207b15..389244d819 100644 --- a/src/google/protobuf/compiler/cpp/file.h +++ b/src/google/protobuf/compiler/cpp/file.h @@ -81,7 +81,8 @@ class PROTOC_EXPORT FileGenerator { // Generates a static initializers with all the existing values from // `static_initializers_`. - // They run in `PROTOBUF_ATTRIBUTE_INIT_PRIORITY2` priority. + // They run in `PROTOBUF_ATTRIBUTE_INIT_PRIORITY1` and + // `PROTOBUF_ATTRIBUTE_INIT_PRIORITY2` priority respectively. void GenerateStaticInitializer(io::Printer* p); // Shared code between the two header generators. @@ -176,7 +177,7 @@ class PROTOC_EXPORT FileGenerator { absl::flat_hash_set weak_deps_; - std::vector> static_initializers_; + std::vector> static_initializers_[2]; const FileDescriptor* file_; Options options_; diff --git a/src/google/protobuf/compiler/cpp/helpers.h b/src/google/protobuf/compiler/cpp/helpers.h index de5f8beb65..4ab98b2761 100644 --- a/src/google/protobuf/compiler/cpp/helpers.h +++ b/src/google/protobuf/compiler/cpp/helpers.h @@ -1176,6 +1176,12 @@ bool HasOnDeserializeTracker(const Descriptor* descriptor, // signature. bool NeedsPostLoopHandler(const Descriptor* descriptor, const Options& options); +// Priority used for static initializers. +enum InitPriority { + kInitPriority101, + kInitPriority102, +}; + } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/cpp/ifndef_guard.cc b/src/google/protobuf/compiler/cpp/ifndef_guard.cc new file mode 100644 index 0000000000..bc04eecebf --- /dev/null +++ b/src/google/protobuf/compiler/cpp/ifndef_guard.cc @@ -0,0 +1,71 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 Google LLC. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +#include "google/protobuf/compiler/cpp/ifndef_guard.h" + +#include + +#include "absl/functional/any_invocable.h" +#include "absl/log/die_if_null.h" +#include "absl/strings/ascii.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_replace.h" +#include "absl/strings/string_view.h" +#include "absl/strings/substitute.h" +#include "google/protobuf/io/printer.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +namespace { + +std::string MakeIfdefGuardIdentifier(const absl::string_view header_path) { + return absl::StrCat(absl::AsciiStrToUpper(absl::StrReplaceAll(header_path, + { + {"/", "_"}, + {".", "_"}, + })), + "_"); +} + +} // namespace + +IfdefGuardPrinter::IfdefGuardPrinter(google::protobuf::io::Printer* const p, + const absl::string_view filename) + : IfdefGuardPrinter(p, filename, MakeIfdefGuardIdentifier) {} + +IfdefGuardPrinter::IfdefGuardPrinter( + google::protobuf::io::Printer* const p, const absl::string_view filename, + absl::AnyInvocable make_ifdef_identifier) + : p_(ABSL_DIE_IF_NULL(p)), + ifdef_identifier_(make_ifdef_identifier(filename)) { + // We can't use variable substitution, because we don't know what delimiter + // to use. + p->Print(absl::Substitute( + R"(#ifndef $0 +#define $0 + +)", + ifdef_identifier_)); +} + +IfdefGuardPrinter::~IfdefGuardPrinter() { + // We can't use variable substitution, because we don't know what delimiter + // to use. + p_->Print(absl::Substitute( + R"( +#endif // $0 +)", + ifdef_identifier_)); +} + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/cpp/ifndef_guard.h b/src/google/protobuf/compiler/cpp/ifndef_guard.h new file mode 100644 index 0000000000..6d7a6fd56a --- /dev/null +++ b/src/google/protobuf/compiler/cpp/ifndef_guard.h @@ -0,0 +1,66 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +// An RAII type for printing an ifdef guard. +// +// This can be used to ensure that appropriate ifdef guards are applied in +// a generated header file. +// +// Example: +// { +// Printer printer(output_stream.get(), '$'); +// const IfdefGuardPrinter ifdef_guard(&printer, output_path); +// // #ifdef guard will be emitted here +// ... +// // #endif will be emitted here +// } +// +// By default, the filename will be converted to a macro by substituting '/' and +// '.' characters with '_'. If a different transformation is required, an +// optional transformation function can be provided. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_IFNDEF_GUARD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_IFNDEF_GUARD_H__ + +#include + +#include "absl/functional/any_invocable.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/io/printer.h" + +// Must be included last. +#include "google/protobuf/port_def.inc" + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +class PROTOC_EXPORT IfdefGuardPrinter final { + public: + explicit IfdefGuardPrinter(google::protobuf::io::Printer* p, + absl::string_view filename); + + explicit IfdefGuardPrinter( + google::protobuf::io::Printer* p, absl::string_view filename, + absl::AnyInvocable make_ifdef_identifier); + + ~IfdefGuardPrinter(); + + private: + google::protobuf::io::Printer* const p_; + const std::string ifdef_identifier_; +}; + +#include "google/protobuf/port_undef.inc" + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_IFNDEF_GUARD_H__ diff --git a/src/google/protobuf/compiler/cpp/ifndef_guard_unittest.cc b/src/google/protobuf/compiler/cpp/ifndef_guard_unittest.cc new file mode 100644 index 0000000000..4e4a823845 --- /dev/null +++ b/src/google/protobuf/compiler/cpp/ifndef_guard_unittest.cc @@ -0,0 +1,92 @@ +#include "google/protobuf/compiler/cpp/ifndef_guard.h" + +#include + +#include +#include "absl/log/absl_check.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream.h" +#include "google/protobuf/io/zero_copy_stream_impl_lite.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +namespace { + +class IfnDefGuardTest : public testing::Test { + protected: + io::ZeroCopyOutputStream* output() { + ABSL_CHECK(stream_.has_value()); + return &*stream_; + } + absl::string_view written() { + stream_.reset(); + return out_; + } + + std::string out_; + absl::optional stream_{&out_}; +}; + +TEST_F(IfnDefGuardTest, Basic) { + { + io::Printer printer(output(), '$'); + + const IfdefGuardPrinter ifdef_guard(&printer, "A/B/E/alpha"); + + EXPECT_FALSE(printer.failed()); + } + + EXPECT_EQ(written(), + "#ifndef A_B_E_ALPHA_\n" + "#define A_B_E_ALPHA_\n" + "\n" + "\n" + "#endif // A_B_E_ALPHA_\n"); +} + +TEST_F(IfnDefGuardTest, DifferentDelim) { + { + io::Printer printer(output(), '\0'); + + const IfdefGuardPrinter ifdef_guard(&printer, "A/B/E/alpha"); + + EXPECT_FALSE(printer.failed()); + } + + EXPECT_EQ(written(), + "#ifndef A_B_E_ALPHA_\n" + "#define A_B_E_ALPHA_\n" + "\n" + "\n" + "#endif // A_B_E_ALPHA_\n"); +} + +TEST_F(IfnDefGuardTest, DifferentSubstitutionFunction) { + { + io::Printer printer(output(), '$'); + + const IfdefGuardPrinter ifdef_guard( + &printer, "A/B/E/alpha", [](absl::string_view) { return "FOO_BAR_"; }); + + EXPECT_FALSE(printer.failed()); + } + + EXPECT_EQ(written(), + "#ifndef FOO_BAR_\n" + "#define FOO_BAR_\n" + "\n" + "\n" + "#endif // FOO_BAR_\n"); +} + +} // namespace + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/cpp/message.cc b/src/google/protobuf/compiler/cpp/message.cc index 463f31a37f..650cd46f50 100644 --- a/src/google/protobuf/compiler/cpp/message.cc +++ b/src/google/protobuf/compiler/cpp/message.cc @@ -3551,6 +3551,19 @@ void MessageGenerator::GenerateClassData(io::Printer* p) { { {"on_demand_register_arena_dtor", on_demand_register_arena_dtor}, {"pin_weak_descriptor", pin_weak_descriptor}, + {"table", + [&] { + // Map entries use the dynamic parser. + if (IsMapEntryMessage(descriptor_)) { + p->Emit(R"cc( + nullptr, // tc_table + )cc"); + } else { + p->Emit(R"cc( + &_table_.header, + )cc"); + } + }}, {"tracker_on_get_metadata", [&] { if (HasTracker(descriptor_, options_)) { @@ -3571,6 +3584,7 @@ void MessageGenerator::GenerateClassData(io::Printer* p) { PROTOBUF_CONSTINIT static const ::$proto_ns$::MessageLite:: ClassDataFull _data_ = { { + $table$, $on_demand_register_arena_dtor$, PROTOBUF_FIELD_OFFSET($classname$, $cached_size$), false, diff --git a/src/google/protobuf/compiler/java/file.cc b/src/google/protobuf/compiler/java/file.cc index 03da25a895..ffee03871f 100644 --- a/src/google/protobuf/compiler/java/file.cc +++ b/src/google/protobuf/compiler/java/file.cc @@ -243,6 +243,9 @@ void FileGenerator::Generate(io::Printer* printer) { // fully-qualified names in the generated source. printer->Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// NO CHECKED-IN PROTOBUF " + // Intentional line breaker + "GENCODE\n" "// source: $filename$\n", "filename", file_->name()); if (options_.opensource_runtime) { @@ -520,6 +523,9 @@ static void GenerateSibling( printer.Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// NO CHECKED-IN PROTOBUF " + // Intentional line breaker + "GENCODE\n" "// source: $filename$\n", "filename", descriptor->file()->name()); if (opensource_runtime) { @@ -600,6 +606,9 @@ std::string FileGenerator::GetKotlinClassname() { void FileGenerator::GenerateKotlin(io::Printer* printer) { printer->Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// NO CHECKED-IN PROTOBUF " + // Intentional line breaker + "GENCODE\n" "// source: $filename$\n" "\n", "filename", file_->name()); @@ -638,6 +647,9 @@ void FileGenerator::GenerateKotlinSiblings( printer.Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// NO CHECKED-IN PROTOBUF " + // Intentional line breaker + "GENCODE\n" "// source: $filename$\n" "\n", "filename", descriptor->file()->name()); diff --git a/src/google/protobuf/compiler/java/generator.cc b/src/google/protobuf/compiler/java/generator.cc index 6a796ff1b9..669adb4bba 100644 --- a/src/google/protobuf/compiler/java/generator.cc +++ b/src/google/protobuf/compiler/java/generator.cc @@ -55,7 +55,6 @@ bool JavaGenerator::Generate(const FileDescriptor* file, file_options.opensource_runtime = opensource_runtime_; - bool enforce_editions = true; for (auto& option : options) { if (option.first == "output_list_file") { file_options.output_list_file = option.second; @@ -75,8 +74,6 @@ bool JavaGenerator::Generate(const FileDescriptor* file, file_options.annotation_list_file = option.second; } else if (option.first == "experimental_strip_nonfunctional_codegen") { file_options.strip_nonfunctional_codegen = true; - } else if (option.first == "experimental_editions") { - enforce_editions = false; } else { *error = absl::StrCat("Unknown generator option: ", option.first); return false; @@ -88,13 +85,6 @@ bool JavaGenerator::Generate(const FileDescriptor* file, return false; } - // TODO: Remove once Java lite supports editions - if (enforce_editions && file_options.enforce_lite && - GetEdition(*file) > google::protobuf::Edition::EDITION_PROTO3) { - *error = "lite runtime generator option cannot be used with editions yet."; - return false; - } - // By default we generate immutable code and shared code for immutable API. if (!file_options.generate_immutable_code && !file_options.generate_mutable_code && diff --git a/src/google/protobuf/compiler/java/java_features.pb.cc b/src/google/protobuf/compiler/java/java_features.pb.cc index 785788ce71..78d404c90c 100644 --- a/src/google/protobuf/compiler/java/java_features.pb.cc +++ b/src/google/protobuf/compiler/java/java_features.pb.cc @@ -6,6 +6,7 @@ #include "google/protobuf/compiler/java/java_features.pb.h" #include +#include #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" @@ -176,6 +177,7 @@ JavaFeatures::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_._cached_size_), false, @@ -366,12 +368,12 @@ namespace protobuf { } // namespace protobuf } // namespace google // @@protoc_insertion_point(global_scope) -PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 -static ::std::false_type _static_init_ PROTOBUF_UNUSED = - (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto), - ::_pbi::ExtensionSet::RegisterMessageExtension( - &::google::protobuf::FeatureSet::default_instance(), 1001, 11, - false, false, &::pb::JavaFeatures::default_instance(), - nullptr, ::_pbi::LazyAnnotation::kUndefined), - ::std::false_type{}); +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ PROTOBUF_UNUSED = + (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto), + ::_pbi::ExtensionSet::RegisterMessageExtension( + &::google::protobuf::FeatureSet::default_instance(), 1001, 11, + false, false, &::pb::JavaFeatures::default_instance(), + nullptr, ::_pbi::LazyAnnotation::kUndefined), + ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/compiler/java/plugin_main.cc b/src/google/protobuf/compiler/java/plugin_main.cc new file mode 100644 index 0000000000..13c6367d3c --- /dev/null +++ b/src/google/protobuf/compiler/java/plugin_main.cc @@ -0,0 +1,10 @@ +#include "google/protobuf/compiler/java/generator.h" +#include "google/protobuf/compiler/plugin.h" + +int main(int argc, char *argv[]) { + ::google::protobuf::compiler::java::JavaGenerator generator; +#ifdef GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE + generator.set_opensource_runtime(true); +#endif + return ::google::protobuf::compiler::PluginMain(argc, argv, &generator); +} diff --git a/src/google/protobuf/compiler/java/shared_code_generator.cc b/src/google/protobuf/compiler/java/shared_code_generator.cc index 16312f2e63..d2bb9a5dd8 100644 --- a/src/google/protobuf/compiler/java/shared_code_generator.cc +++ b/src/google/protobuf/compiler/java/shared_code_generator.cc @@ -59,6 +59,9 @@ void SharedCodeGenerator::Generate( std::string info_full_path = absl::StrCat(filename, ".pb.meta"); printer->Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// NO CHECKED-IN PROTOBUF " + // Intentional line breaker + "GENCODE\n" "// source: $filename$\n", "filename", file_->name()); if (options_.opensource_runtime) { diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc index af1b09c05d..0e7744c22b 100644 --- a/src/google/protobuf/compiler/mock_code_generator.cc +++ b/src/google/protobuf/compiler/mock_code_generator.cc @@ -50,6 +50,7 @@ namespace google { namespace protobuf { namespace compiler { +namespace { // Returns the list of the names of files in all_files in the form of a // comma-separated string. @@ -71,14 +72,20 @@ static constexpr absl::string_view kFirstInsertionPoint = static constexpr absl::string_view kSecondInsertionPoint = " # @@protoc_insertion_point(second_mock_insertion_point) is here\n"; -MockCodeGenerator::MockCodeGenerator(absl::string_view name) : name_(name) { +absl::string_view GetTestCase() { const char* c_key = getenv("TEST_CASE"); if (c_key == nullptr) { // In Windows, setting 'TEST_CASE=' is equivalent to unsetting // and therefore c_key can be nullptr - c_key = ""; + return ""; } - absl::string_view key(c_key); + return c_key; +} + +} // namespace + +MockCodeGenerator::MockCodeGenerator(absl::string_view name) : name_(name) { + absl::string_view key = GetTestCase(); if (key == "no_editions") { suppressed_features_ |= CodeGenerator::FEATURE_SUPPORTS_EDITIONS; } else if (key == "invalid_features") { @@ -214,7 +221,7 @@ bool MockCodeGenerator::Generate(const FileDescriptor* file, std::string* error) const { // Override minimum/maximum after generating the pool to simulate a plugin // that "works" but doesn't advertise support of the current edition. - absl::string_view test_case = getenv("TEST_CASE"); + absl::string_view test_case = GetTestCase(); if (test_case == "high_minimum") { minimum_edition_ = Edition::EDITION_99997_TEST_ONLY; } else if (test_case == "low_maximum") { @@ -227,9 +234,9 @@ bool MockCodeGenerator::Generate(const FileDescriptor* file, const FeatureSet& features = GetResolvedSourceFeatures(descriptor); ABSL_CHECK(features.HasExtension(pb::test)) << "Test features were not resolved properly"; - ABSL_CHECK(features.GetExtension(pb::test).has_int_file_feature()) + ABSL_CHECK(features.GetExtension(pb::test).has_file_feature()) << "Test features were not resolved properly"; - ABSL_CHECK(features.GetExtension(pb::test).has_int_source_feature()) + ABSL_CHECK(features.GetExtension(pb::test).has_source_feature()) << "Test features were not resolved properly"; }); } diff --git a/src/google/protobuf/compiler/php/names.cc b/src/google/protobuf/compiler/php/names.cc index 79274766e1..135b55b94e 100644 --- a/src/google/protobuf/compiler/php/names.cc +++ b/src/google/protobuf/compiler/php/names.cc @@ -7,10 +7,11 @@ #include "google/protobuf/compiler/php/names.h" +#include #include -#include "google/protobuf/compiler/code_generator.h" -#include "google/protobuf/compiler/plugin.h" +#include "absl/strings/ascii.h" +#include "absl/strings/string_view.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" @@ -39,8 +40,7 @@ namespace compiler { namespace php { bool IsReservedName(absl::string_view name) { - std::string lower(name); - std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); + std::string lower = absl::AsciiStrToLower(name); for (int i = 0; i < kReservedNamesSize; i++) { if (lower == kReservedNames[i]) { return true; diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc index 8ee6924522..6c00ea5af3 100644 --- a/src/google/protobuf/compiler/php/php_generator.cc +++ b/src/google/protobuf/compiler/php/php_generator.cc @@ -106,8 +106,7 @@ std::string DescriptorFullName(const DescriptorType* desc, bool is_internal) { std::string ConstantNamePrefix(absl::string_view classname) { bool is_reserved = false; - std::string lower(classname); - std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); + std::string lower = absl::AsciiStrToLower(classname); is_reserved = IsReservedName(lower); @@ -513,7 +512,7 @@ std::string BinaryToPhpString(const std::string& src) { if (src[i] == '\\' || src[i] == '$' || src[i] == '"') { dest += '\\'; dest += src[i]; - } else if (std::isprint(src[i])) { + } else if (absl::ascii_isprint(src[i])) { dest += src[i]; } else { dest += '\\'; diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index ced93f9fc1..aef3971530 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -6,6 +6,7 @@ #include "google/protobuf/compiler/plugin.pb.h" #include +#include #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" @@ -362,6 +363,7 @@ Version::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Version, _impl_._cached_size_), false, @@ -673,6 +675,7 @@ CodeGeneratorRequest::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(CodeGeneratorRequest, _impl_._cached_size_), false, @@ -1020,6 +1023,7 @@ CodeGeneratorResponse_File::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse_File, _impl_._cached_size_), false, @@ -1340,6 +1344,7 @@ CodeGeneratorResponse::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_._cached_size_), false, @@ -1611,8 +1616,8 @@ namespace protobuf { } // namespace protobuf } // namespace google // @@protoc_insertion_point(global_scope) -PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 -static ::std::false_type _static_init_ PROTOBUF_UNUSED = - (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto), - ::std::false_type{}); +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ PROTOBUF_UNUSED = + (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto), + ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/compiler/python/generator.cc b/src/google/protobuf/compiler/python/generator.cc index fbfe5fd562..8877995ed4 100644 --- a/src/google/protobuf/compiler/python/generator.cc +++ b/src/google/protobuf/compiler/python/generator.cc @@ -29,6 +29,7 @@ #include #include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/memory/memory.h" @@ -353,6 +354,9 @@ void Generator::PrintTopBoilerplate() const { printer_->Print( "# -*- coding: utf-8 -*-\n" "# Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "# NO CHECKED-IN PROTOBUF " + // Intentional line breaker + "GENCODE\n" "# source: $filename$\n", "filename", file_->name()); if (opensource_runtime_) { @@ -367,12 +371,35 @@ void Generator::PrintTopBoilerplate() const { // instead uses aliases assigned when importing modules. printer_->Print("import google3\n"); } + bool runtime_version_disabled = false; printer_->Print( "from google.protobuf import descriptor as _descriptor\n" "from google.protobuf import descriptor_pool as _descriptor_pool\n" + "$runtime_version_import$" "from google.protobuf import symbol_database as _symbol_database\n" - "from google.protobuf.internal import builder as _builder\n"); - + "from google.protobuf.internal import builder as _builder\n", + "runtime_version_import", + runtime_version_disabled ? "" + : "from google.protobuf import runtime_version " + "as _runtime_version\n"); + if (!runtime_version_disabled) { + const auto& version = GetProtobufPythonVersion(opensource_runtime_); + printer_->Print( + "_runtime_version.ValidateProtobufRuntimeVersion(\n" + " $domain$,\n" + " $major$,\n" + " $minor$,\n" + " $patch$,\n" + " '$suffix$',\n" + " '$location$'\n" + ")\n", + "domain", + opensource_runtime_ ? "_runtime_version.Domain.PUBLIC" + : "_runtime_version.Domain.GOOGLE_INTERNAL", + "major", absl::StrCat(version.major()), "minor", + absl::StrCat(version.minor()), "patch", absl::StrCat(version.patch()), + "suffix", version.suffix(), "location", file_->name()); + } printer_->Print("# @@protoc_insertion_point(imports)\n\n"); printer_->Print("_sym_db = _symbol_database.Default()\n"); printer_->Print("\n\n"); diff --git a/src/google/protobuf/compiler/python/plugin_main.cc b/src/google/protobuf/compiler/python/plugin_main.cc new file mode 100644 index 0000000000..c9c9a57e51 --- /dev/null +++ b/src/google/protobuf/compiler/python/plugin_main.cc @@ -0,0 +1,11 @@ +#include "google/protobuf/compiler/plugin.h" +#include "google/protobuf/compiler/python/generator.h" + +int main(int argc, char *argv[]) { + ::google::protobuf::compiler::python::Generator generator; +#ifdef GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE + generator.set_opensource_runtime(true); + generator.set_runtime_include_base(GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE); +#endif + return ::google::protobuf::compiler::PluginMain(argc, argv, &generator); +} diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.h b/src/google/protobuf/compiler/ruby/ruby_generator.h index b1164ecd37..55d33a30df 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.h +++ b/src/google/protobuf/compiler/ruby/ruby_generator.h @@ -13,7 +13,6 @@ #include #include "google/protobuf/compiler/code_generator.h" - #include "google/protobuf/port_def.inc" namespace google { @@ -30,8 +29,11 @@ class PROTOC_EXPORT Generator : public CodeGenerator { GeneratorContext* generator_context, std::string* error) const override; uint64_t GetSupportedFeatures() const override { - return FEATURE_PROTO3_OPTIONAL; + return Feature::FEATURE_PROTO3_OPTIONAL | + Feature::FEATURE_SUPPORTS_EDITIONS; } + Edition GetMinimumEdition() const override { return Edition::EDITION_PROTO2; } + Edition GetMaximumEdition() const override { return Edition::EDITION_2023; } }; } // namespace ruby diff --git a/src/google/protobuf/compiler/rust/accessors/singular_message.cc b/src/google/protobuf/compiler/rust/accessors/singular_message.cc index c8e44b99af..179d48c25a 100644 --- a/src/google/protobuf/compiler/rust/accessors/singular_message.cc +++ b/src/google/protobuf/compiler/rust/accessors/singular_message.cc @@ -73,7 +73,18 @@ void SingularMessage::InMsgImpl(Context& ctx, const FieldDescriptor& field, return; } ctx.Emit({}, R"rs( - pub fn $raw_field_name$_mut(&mut self) + pub fn $raw_field_name$_mut(&mut self) -> $msg_type$Mut<'_> { + self.$raw_field_name$_entry().or_default() + } + )rs"); + }}, + {"private_getter_entry", + [&] { + if (accessor_case == AccessorCase::VIEW) { + return; + } + ctx.Emit({}, R"rs( + fn $raw_field_name$_entry(&mut self) -> $pb$::FieldEntry<'_, $msg_type$> { static VTABLE: $pbr$::MessageVTable = $pbr$::MessageVTable::new($pbi$::Private, @@ -81,7 +92,7 @@ void SingularMessage::InMsgImpl(Context& ctx, const FieldDescriptor& field, $getter_mut_thunk$, $clearer_thunk$); unsafe { - let has = $hazzer_thunk$(self.raw_msg()); + let has = self.has_$raw_field_name$(); $pbi$::new_vtable_field_entry($pbi$::Private, self.as_mutator_message_ref(), &VTABLE, @@ -96,9 +107,7 @@ void SingularMessage::InMsgImpl(Context& ctx, const FieldDescriptor& field, pub fn $raw_field_name$_opt($view_self$) -> $pb$::Optional<$msg_type$View<$view_lifetime$>> { let view = self.$field$(); - $pb$::Optional::new(view, unsafe { - $hazzer_thunk$(self.raw_msg()) - }) + $pb$::Optional::new(view, self.has_$raw_field_name$()) } )rs"); }}, @@ -109,10 +118,17 @@ void SingularMessage::InMsgImpl(Context& ctx, const FieldDescriptor& field, pub fn set_$raw_field_name$(&mut self, val: impl $pb$::SettableValue<$msg_type$>) { //~ TODO: Optimize this to not go through the //~ FieldEntry. - self.$raw_field_name$_mut().set(val); + self.$raw_field_name$_entry().set(val); } )rs"); }}, + {"hazzer", + [&] { + ctx.Emit({}, R"rs( + pub fn has_$raw_field_name$($view_self$) -> bool { + unsafe { $hazzer_thunk$(self.raw_msg()) } + })rs"); + }}, {"clearer", [&] { if (accessor_case == AccessorCase::VIEW) return; @@ -124,8 +140,10 @@ void SingularMessage::InMsgImpl(Context& ctx, const FieldDescriptor& field, R"rs( $getter$ $getter_mut$ + $private_getter_entry$ $getter_opt$ $setter$ + $hazzer$ $clearer$ )rs"); } diff --git a/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc b/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc index 3d552ed222..da12ec585a 100644 --- a/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc +++ b/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc @@ -41,15 +41,14 @@ void SingularScalar::InMsgImpl(Context& ctx, const FieldDescriptor& field, }}, {"getter_opt", [&] { - if (!field.is_optional()) return; if (!field.has_presence()) return; ctx.Emit(R"rs( pub fn $raw_field_name$_opt($view_self$) -> $pb$::Optional<$Scalar$> { - if !unsafe { $hazzer_thunk$(self.raw_msg()) } { - return $pb$::Optional::Unset($default_value$); + if self.has_$raw_field_name$() { + $pb$::Optional::Set(self.$field$()) + } else { + $pb$::Optional::Unset($default_value$) } - let value = unsafe { $getter_thunk$(self.raw_msg()) }; - $pb$::Optional::Set(value) } )rs"); }}, @@ -62,6 +61,14 @@ void SingularScalar::InMsgImpl(Context& ctx, const FieldDescriptor& field, } )rs"); }}, + {"hazzer", + [&] { + if (!field.has_presence()) return; + ctx.Emit({}, R"rs( + pub fn has_$raw_field_name$($view_self$) -> bool { + unsafe { $hazzer_thunk$(self.raw_msg()) } + })rs"); + }}, {"clearer", [&] { if (accessor_case == AccessorCase::VIEW) return; @@ -74,83 +81,13 @@ void SingularScalar::InMsgImpl(Context& ctx, const FieldDescriptor& field, {"getter_thunk", ThunkName(ctx, field, "get")}, {"setter_thunk", ThunkName(ctx, field, "set")}, {"clearer_thunk", ThunkName(ctx, field, "clear")}, - {"vtable_name", VTableName(field)}, - {"vtable", - [&] { - if (accessor_case != AccessorCase::OWNED) { - return; - } - if (field.has_presence()) { - ctx.Emit(R"rs( - const $vtable_name$: &'static $pbi$::PrimitiveOptionalMutVTable<$Scalar$> = - &$pbi$::PrimitiveOptionalMutVTable::new( - $pbi$::Private, - $getter_thunk$, - $setter_thunk$, - $clearer_thunk$, - $default_value$, - ); - )rs"); - } else { - ctx.Emit(R"rs( - const $vtable_name$: &'static $pbi$::PrimitiveVTable<$Scalar$> = - &$pbi$::PrimitiveVTable::new( - $pbi$::Private, - $getter_thunk$, - $setter_thunk$, - ); - )rs"); - } - }}, - {"getter_mut", - [&] { - if (accessor_case == AccessorCase::VIEW) { - return; - } - if (field.has_presence()) { - ctx.Emit(R"rs( - pub fn $raw_field_name$_mut(&mut self) -> $pb$::FieldEntry<'_, $Scalar$> { - unsafe { - let has = $hazzer_thunk$(self.raw_msg()); - $pbi$::new_vtable_field_entry::<$Scalar$>( - $pbi$::Private, - self.as_mutator_message_ref(), - $Msg$::$vtable_name$, - has, - ) - } - } - )rs"); - } else { - ctx.Emit(R"rs( - pub fn $raw_field_name$_mut(&mut self) -> $pb$::Mut<'_, $Scalar$> { - // SAFETY: - // - The message is valid for the output lifetime. - // - The vtable is valid for the field. - // - There is no way to mutate the element for the output - // lifetime except through this mutator. - unsafe { - $pb$::PrimitiveMut::from_inner( - $pbi$::Private, - $pbi$::RawVTableMutator::new( - $pbi$::Private, - self.as_mutator_message_ref(), - $Msg$::$vtable_name$, - ), - ) - } - } - )rs"); - } - }}, }, R"rs( $getter$ $getter_opt$ $setter$ + $hazzer$ $clearer$ - $vtable$ - $getter_mut$ )rs"); } diff --git a/src/google/protobuf/compiler/rust/accessors/singular_string.cc b/src/google/protobuf/compiler/rust/accessors/singular_string.cc index b654edb604..9328e7b827 100644 --- a/src/google/protobuf/compiler/rust/accessors/singular_string.cc +++ b/src/google/protobuf/compiler/rust/accessors/singular_string.cc @@ -69,10 +69,9 @@ void SingularString::InMsgImpl(Context& ctx, const FieldDescriptor& field, if (!field.has_presence()) return; ctx.Emit(R"rs( pub fn $raw_field_name$_opt($view_self$) -> $pb$::Optional<&$view_lifetime$ $proxied_type$> { - let view = unsafe { $getter_thunk$(self.raw_msg()).as_ref() }; $pb$::Optional::new( - $transform_view$, - unsafe { $hazzer_thunk$(self.raw_msg()) } + self.$field$(), + self.has_$raw_field_name$() ) } )rs"); @@ -88,6 +87,14 @@ void SingularString::InMsgImpl(Context& ctx, const FieldDescriptor& field, } )rs"); }}, + {"hazzer", + [&] { + if (!field.has_presence()) return; + ctx.Emit({}, R"rs( + pub fn has_$raw_field_name$($view_self$) -> bool { + unsafe { $hazzer_thunk$(self.raw_msg()) } + })rs"); + }}, {"clearer", [&] { if (accessor_case == AccessorCase::VIEW) return; @@ -135,7 +142,7 @@ void SingularString::InMsgImpl(Context& ctx, const FieldDescriptor& field, } if (field.has_presence()) { ctx.Emit(R"rs( - pub fn $raw_field_name$_mut(&mut self) -> $pb$::FieldEntry<'_, $proxied_type$> { + fn $raw_field_name$_mut(&mut self) -> $pb$::FieldEntry<'_, $proxied_type$> { let out = unsafe { let has = $hazzer_thunk$(self.raw_msg()); $pbi$::new_vtable_field_entry( @@ -150,7 +157,7 @@ void SingularString::InMsgImpl(Context& ctx, const FieldDescriptor& field, )rs"); } else { ctx.Emit(R"rs( - pub fn $raw_field_name$_mut(&mut self) -> $pb$::Mut<'_, $proxied_type$> { + fn $raw_field_name$_mut(&mut self) -> $pb$::Mut<'_, $proxied_type$> { unsafe { <$pb$::Mut<$proxied_type$>>::from_inner( $pbi$::Private, @@ -170,6 +177,7 @@ void SingularString::InMsgImpl(Context& ctx, const FieldDescriptor& field, $getter$ $getter_opt$ $setter$ + $hazzer$ $clearer$ $vtable$ $field_mutator_getter$ diff --git a/src/google/protobuf/compiler/rust/enum.cc b/src/google/protobuf/compiler/rust/enum.cc index 3ca943ac42..ae216fea6f 100644 --- a/src/google/protobuf/compiler/rust/enum.cc +++ b/src/google/protobuf/compiler/rust/enum.cc @@ -177,7 +177,7 @@ void EnumProxiedInMapValue(Context& ctx, const EnumDescriptor& desc) { $pbr$::InnerMap::new($pbi$::Private, raw, arena)) } - unsafe fn map_free(_private: $pbi$::Private, map: &mut $pb$::Map<$key_t$, Self>) { + unsafe fn map_free(_private: $pbi$::Private, _map: &mut $pb$::Map<$key_t$, Self>) { // No-op: the memory will be dropped by the arena. } @@ -497,7 +497,7 @@ void GenerateEnumThunksCc(Context& ctx, const EnumDescriptor& desc) { ctx.Emit( { {"cpp_t", cpp::QualifiedClassName(&desc)}, - {"rs_t", GetUnderscoreDelimitedFullName(ctx, desc)}, + {"rs_t", UnderscoreDelimitFullName(ctx, desc.full_name())}, {"abi", "\"C\""}, // Workaround for syntax highlight bug in VSCode. }, R"cc( diff --git a/src/google/protobuf/compiler/rust/message.cc b/src/google/protobuf/compiler/rust/message.cc index d72ac9fb47..00dc6fa002 100644 --- a/src/google/protobuf/compiler/rust/message.cc +++ b/src/google/protobuf/compiler/rust/message.cc @@ -597,7 +597,7 @@ void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) { $pbr$::InnerMap::new($pbi$::Private, raw, arena)) } - unsafe fn map_free(_private: $pbi$::Private, map: &mut $pb$::Map<$key_t$, Self>) { + unsafe fn map_free(_private: $pbi$::Private, _map: &mut $pb$::Map<$key_t$, Self>) { // No-op: the memory will be dropped by the arena. } @@ -712,12 +712,12 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { {"nested_in_msg", [&] { // If we have no nested types, enums, or oneofs, bail out without - // emitting an empty mod SomeMsg_. + // emitting an empty mod some_msg. if (msg.nested_type_count() == 0 && msg.enum_type_count() == 0 && msg.real_oneof_decl_count() == 0) { return; } - ctx.Emit({{"Msg", RsSafeName(msg.name())}, + ctx.Emit({{"mod_name", RsSafeName(CamelToSnakeCase(msg.name()))}, {"nested_msgs", [&] { for (int i = 0; i < msg.nested_type_count(); ++i) { @@ -737,13 +737,12 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { } }}}, R"rs( - #[allow(non_snake_case)] - pub mod $Msg$_ { + pub mod $mod_name$ { $nested_msgs$ $nested_enums$ $oneofs$ - } // mod $Msg$_ + } // mod $mod_name$ )rs"); }}, {"raw_arena_getter_for_message", @@ -816,6 +815,12 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { } } + impl std::default::Default for $Msg$ { + fn default() -> Self { + Self::new() + } + } + // SAFETY: // - `$Msg$` is `Sync` because it does not implement interior mutability. // Neither does `$Msg$Mut`. @@ -986,6 +991,9 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { Self{ inner: $pbr$::MutatorMessageRef::new(_private, msg) } } + #[deprecated = "This .or_default() is a no-op, usages can be safely removed"] + pub fn or_default(self) -> Self { self } + fn raw_msg(&self) -> $pbi$::RawMessage { self.inner.msg() } diff --git a/src/google/protobuf/compiler/rust/naming.cc b/src/google/protobuf/compiler/rust/naming.cc index 39ff326ff8..85f1548c09 100644 --- a/src/google/protobuf/compiler/rust/naming.cc +++ b/src/google/protobuf/compiler/rust/naming.cc @@ -131,28 +131,6 @@ std::string ThunkMapOrRepeated(Context& ctx, const FieldDescriptor& field, return thunkName; } -std::string RustModule(Context& ctx, const Descriptor* containing_type) { - std::vector modules; - - // Innermost to outermost order. - const Descriptor* parent = containing_type; - while (parent != nullptr) { - modules.push_back(absl::StrCat(parent->name(), "_")); - parent = parent->containing_type(); - } - - // Reverse the vector to get submodules in outer-to-inner order). - std::reverse(modules.begin(), modules.end()); - - // If there are any modules at all, push an empty string on the end so that - // we get the trailing :: - if (!modules.empty()) { - modules.push_back(""); - } - - return absl::StrJoin(modules, "::"); -} - } // namespace std::string ThunkName(Context& ctx, const FieldDescriptor& field, @@ -179,32 +157,23 @@ std::string VTableName(const FieldDescriptor& field) { return absl::StrCat("__", absl::AsciiStrToUpper(field.name()), "_VTABLE"); } -std::string GetFullyQualifiedPath(Context& ctx, const Descriptor& msg) { - auto rel_path = GetCrateRelativeQualifiedPath(ctx, msg); - if (IsInCurrentlyGeneratingCrate(ctx, msg)) { - return absl::StrCat("crate::", rel_path); - } - return absl::StrCat(GetCrateName(ctx, *msg.file()), "::", rel_path); -} - -std::string GetFullyQualifiedPath(Context& ctx, const EnumDescriptor& enum_) { - auto rel_path = GetCrateRelativeQualifiedPath(ctx, enum_); - if (IsInCurrentlyGeneratingCrate(ctx, enum_)) { +template +std::string GetFullyQualifiedPath(Context& ctx, const Desc& desc) { + auto rel_path = GetCrateRelativeQualifiedPath(ctx, desc); + if (IsInCurrentlyGeneratingCrate(ctx, desc)) { return absl::StrCat("crate::", rel_path); } - return absl::StrCat(GetCrateName(ctx, *enum_.file()), "::", rel_path); + return absl::StrCat(GetCrateName(ctx, *desc.file()), "::", rel_path); } -std::string GetUnderscoreDelimitedFullName(Context& ctx, - const Descriptor& msg) { - std::string result = msg.full_name(); - absl::StrReplaceAll({{".", "_"}}, &result); - return result; +template +std::string GetUnderscoreDelimitedFullName(Context& ctx, const Desc& desc) { + return UnderscoreDelimitFullName(ctx, desc.full_name()); } -std::string GetUnderscoreDelimitedFullName(Context& ctx, - const EnumDescriptor& enum_) { - std::string result = enum_.full_name(); +std::string UnderscoreDelimitFullName(Context& ctx, + absl::string_view full_name) { + std::string result = std::string(full_name); absl::StrReplaceAll({{".", "_"}}, &result); return result; } @@ -237,12 +206,39 @@ std::string RsTypePath(Context& ctx, const FieldDescriptor& field) { ABSL_LOG(FATAL) << "Unsupported field type: " << field.type_name(); } +std::string RustModuleForContainingType(Context& ctx, + const Descriptor* containing_type) { + std::vector modules; + + // Innermost to outermost order. + const Descriptor* parent = containing_type; + while (parent != nullptr) { + modules.push_back(RsSafeName(CamelToSnakeCase(parent->name()))); + parent = parent->containing_type(); + } + + // Reverse the vector to get submodules in outer-to-inner order). + std::reverse(modules.begin(), modules.end()); + + // If there are any modules at all, push an empty string on the end so that + // we get the trailing :: + if (!modules.empty()) { + modules.push_back(""); + } + + return absl::StrJoin(modules, "::"); +} + std::string RustModule(Context& ctx, const Descriptor& msg) { - return RustModule(ctx, msg.containing_type()); + return RustModuleForContainingType(ctx, msg.containing_type()); } std::string RustModule(Context& ctx, const EnumDescriptor& enum_) { - return RustModule(ctx, enum_.containing_type()); + return RustModuleForContainingType(ctx, enum_.containing_type()); +} + +std::string RustModule(Context& ctx, const OneofDescriptor& oneof) { + return RustModuleForContainingType(ctx, oneof.containing_type()); } std::string RustInternalModuleName(Context& ctx, const FileDescriptor& file) { @@ -316,10 +312,6 @@ std::string OneofViewEnumRsName(const OneofDescriptor& oneof) { return RsSafeName(SnakeToUpperCamelCase(oneof.name())); } -std::string OneofMutEnumRsName(const OneofDescriptor& oneof) { - return SnakeToUpperCamelCase(oneof.name()) + "Mut"; -} - std::string OneofCaseEnumRsName(const OneofDescriptor& oneof) { // Note: This is the name used for the cpp Case enum, we use it for both // the Rust Case enum as well as for the cpp case enum in the cpp thunk. diff --git a/src/google/protobuf/compiler/rust/naming.h b/src/google/protobuf/compiler/rust/naming.h index 2928c5dccb..2be35da405 100644 --- a/src/google/protobuf/compiler/rust/naming.h +++ b/src/google/protobuf/compiler/rust/naming.h @@ -50,7 +50,6 @@ std::string EnumRsName(const EnumDescriptor& desc); std::string EnumValueRsName(const EnumValueDescriptor& value); std::string OneofViewEnumRsName(const OneofDescriptor& oneof); -std::string OneofMutEnumRsName(const OneofDescriptor& oneof); std::string OneofCaseEnumRsName(const OneofDescriptor& oneof); std::string OneofCaseRsName(const FieldDescriptor& oneof_field); @@ -69,17 +68,24 @@ std::string RsSafeName(absl::string_view name); // // If the message has no package and no containing messages then this returns // empty string. +std::string RustModuleForContainingType(Context& ctx, + const Descriptor* containing_type); std::string RustModule(Context& ctx, const Descriptor& msg); std::string RustModule(Context& ctx, const EnumDescriptor& enum_); +std::string RustModule(Context& ctx, const OneofDescriptor& oneof); std::string RustInternalModuleName(Context& ctx, const FileDescriptor& file); std::string GetCrateRelativeQualifiedPath(Context& ctx, const Descriptor& msg); std::string GetCrateRelativeQualifiedPath(Context& ctx, const EnumDescriptor& enum_); +std::string GetCrateRelativeQualifiedPath(Context& ctx, + const OneofDescriptor& oneof); + +template +std::string GetUnderscoreDelimitedFullName(Context& ctx, const Desc& desc); -std::string GetUnderscoreDelimitedFullName(Context& ctx, const Descriptor& msg); -std::string GetUnderscoreDelimitedFullName(Context& ctx, - const EnumDescriptor& enum_); +std::string UnderscoreDelimitFullName(Context& ctx, + absl::string_view full_name); // TODO: Unify these with other case-conversion functions. diff --git a/src/google/protobuf/compiler/rust/oneof.cc b/src/google/protobuf/compiler/rust/oneof.cc index 380fcfe175..f2c82a876c 100644 --- a/src/google/protobuf/compiler/rust/oneof.cc +++ b/src/google/protobuf/compiler/rust/oneof.cc @@ -24,17 +24,12 @@ namespace protobuf { namespace compiler { namespace rust { -// We emit three Rust enums: +// For each oneof we emit two Rust enums with corresponding accessors: // - An enum acting as a tagged union that has each case holds a View<> of // each of the cases. Named as the one_of name in CamelCase. -// - An enum acting as a tagged union that has each case holds a Mut<> of -// each of the cases. Named as one_of name in CamelCase with "Mut" appended. -// [TODO: Mut not implemented yet]. -// - A simple enum whose cases have int values matching the cpp or upb's -// case enum. Named as the one_of camelcase with "Case" appended. -// All three contain cases matching the fields in the oneof CamelCased. -// The first and second are exposed in the API, the third is internal and -// used for interop with the Kernels in the generation of the other two. +// - A simple 'which oneof field is set' enum which directly maps to the +// underlying enum used for the 'cases' accessor in C++ or upb. Named as the +// one_of camelcase with "Case" appended. // // Example: // For this oneof: @@ -46,29 +41,31 @@ namespace rust { // } // // This will emit as the exposed API: -// pub mod SomeMsg_ { -// // The 'view' struct (no suffix on the name) +// pub mod some_msg { // pub enum SomeOneof<'msg> { // FieldA(i32) = 7, // FieldB(View<'msg, SomeMsg>) = 9, // not_set(std::marker::PhantomData<&'msg ()>) = 0 // } -// pub enum SomeOneofMut<'msg> { -// FieldA(Mut<'msg, i32>) = 7, -// FieldB(Mut<'msg, SomeMsg>) = 9, -// not_set(std::marker::PhantomData<&'msg ()>) = 0 +// +// #[repr(C)] +// pub enum SomeOneofCase { +// FieldA = 7, +// FieldB = 9, +// not_set = 0 // } // } // impl SomeMsg { // pub fn some_oneof(&self) -> SomeOneof {...} -// pub fn some_oneof_mut(&mut self) -> SomeOneofMut {...} +// pub fn some_oneof_case(&self) -> SomeOneofCase {...} // } // impl SomeMsgMut { // pub fn some_oneof(&self) -> SomeOneof {...} -// pub fn some_oneof_mut(&mut self) -> SomeOneofMut {...} +// pub fn some_oneof_case(&self) -> SomeOneofCase {...} // } // impl SomeMsgView { -// pub fn some_oneof(&self) -> SomeOneof {...} +// pub fn some_oneof(self) -> SomeOneof {...} +// pub fn some_oneof_case(self) -> SomeOneofCase {...} // } // // An additional "Case" enum which just reflects the corresponding slot numbers @@ -110,71 +107,28 @@ std::string RsTypeNameView(Context& ctx, const FieldDescriptor& field) { return ""; } -// A user-friendly rust type for a mutator of this field with lifetime 'msg. -std::string RsTypeNameMut(Context& ctx, const FieldDescriptor& field) { - if (field.options().has_ctype()) { - return ""; // TODO: b/308792377 - ctype fields not supported yet. - } - switch (GetRustFieldType(field)) { - case RustFieldType::INT32: - case RustFieldType::INT64: - case RustFieldType::UINT32: - case RustFieldType::UINT64: - case RustFieldType::FLOAT: - case RustFieldType::DOUBLE: - case RustFieldType::BOOL: - return absl::StrCat("::__pb::PrimitiveMut<'msg, ", RsTypePath(ctx, field), - ">"); - case RustFieldType::BYTES: - return "::__pb::BytesMut<'msg>"; - case RustFieldType::STRING: - return "::__pb::ProtoStrMut<'msg>"; - case RustFieldType::MESSAGE: - return absl::StrCat("::__pb::Mut<'msg, ", RsTypePath(ctx, field), ">"); - case RustFieldType::ENUM: - return absl::StrCat("::__pb::Mut<'msg, ", RsTypePath(ctx, field), ">"); - } - - ABSL_LOG(FATAL) << "Unexpected field type: " << field.type_name(); - return ""; -} - } // namespace void GenerateOneofDefinition(Context& ctx, const OneofDescriptor& oneof) { ctx.Emit( - {{"view_enum_name", OneofViewEnumRsName(oneof)}, - {"mut_enum_name", OneofMutEnumRsName(oneof)}, - {"view_fields", - [&] { - for (int i = 0; i < oneof.field_count(); ++i) { - auto& field = *oneof.field(i); - std::string rs_type = RsTypeNameView(ctx, field); - if (rs_type.empty()) { - continue; - } - ctx.Emit({{"name", OneofCaseRsName(field)}, - {"type", rs_type}, - {"number", std::to_string(field.number())}}, - R"rs($name$($type$) = $number$, - )rs"); - } - }}, - {"mut_fields", - [&] { - for (int i = 0; i < oneof.field_count(); ++i) { - auto& field = *oneof.field(i); - std::string rs_type = RsTypeNameMut(ctx, field); - if (rs_type.empty()) { - continue; - } - ctx.Emit({{"name", OneofCaseRsName(field)}, - {"type", rs_type}, - {"number", std::to_string(field.number())}}, - R"rs($name$($type$) = $number$, + { + {"view_enum_name", OneofViewEnumRsName(oneof)}, + {"view_fields", + [&] { + for (int i = 0; i < oneof.field_count(); ++i) { + auto& field = *oneof.field(i); + std::string rs_type = RsTypeNameView(ctx, field); + if (rs_type.empty()) { + continue; + } + ctx.Emit({{"name", OneofCaseRsName(field)}, + {"type", rs_type}, + {"number", std::to_string(field.number())}}, + R"rs($name$($type$) = $number$, )rs"); - } - }}}, + } + }}, + }, // TODO: Revisit if isize is the optimal repr for this enum. // TODO: not_set currently has phantom data just to avoid the // lifetime on the enum breaking compilation if there are zero supported @@ -190,18 +144,6 @@ void GenerateOneofDefinition(Context& ctx, const OneofDescriptor& oneof) { #[allow(non_camel_case_types)] not_set(std::marker::PhantomData<&'msg ()>) = 0 } - - #[non_exhaustive] - #[derive(Debug)] - #[allow(dead_code)] - #[repr(isize)] - pub enum $mut_enum_name$<'msg> { - $mut_fields$ - - #[allow(non_camel_case_types)] - not_set(std::marker::PhantomData<&'msg ()>) = 0 - } - )rs"); // Note: This enum is used as the Thunk return type for getting which case is @@ -221,7 +163,7 @@ void GenerateOneofDefinition(Context& ctx, const OneofDescriptor& oneof) { #[repr(C)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[allow(dead_code)] - pub(super) enum $case_enum_name$ { + pub enum $case_enum_name$ { $cases$ #[allow(non_camel_case_types)] @@ -234,103 +176,62 @@ void GenerateOneofDefinition(Context& ctx, const OneofDescriptor& oneof) { void GenerateOneofAccessors(Context& ctx, const OneofDescriptor& oneof, AccessorCase accessor_case) { ctx.Emit( - {{"oneof_name", RsSafeName(oneof.name())}, - {"view_lifetime", ViewLifetime(accessor_case)}, - {"view_self", ViewReceiver(accessor_case)}, - {"view_enum_name", OneofViewEnumRsName(oneof)}, - {"mut_enum_name", OneofMutEnumRsName(oneof)}, - {"case_enum_name", OneofCaseEnumRsName(oneof)}, - {"view_cases", - [&] { - for (int i = 0; i < oneof.field_count(); ++i) { - auto& field = *oneof.field(i); - std::string rs_type = RsTypeNameView(ctx, field); - if (rs_type.empty()) { - continue; - } - ctx.Emit( - { - {"case", OneofCaseRsName(field)}, - {"rs_getter", RsSafeName(field.name())}, - {"type", rs_type}, - }, - R"rs( - $Msg$_::$case_enum_name$::$case$ => - $Msg$_::$view_enum_name$::$case$(self.$rs_getter$()), + { + {"oneof_name", RsSafeName(oneof.name())}, + {"view_lifetime", ViewLifetime(accessor_case)}, + {"self", ViewReceiver(accessor_case)}, + {"oneof_enum_module", + absl::StrCat("crate::", RustModuleForContainingType( + ctx, oneof.containing_type()))}, + {"view_enum_name", OneofViewEnumRsName(oneof)}, + {"case_enum_name", OneofCaseEnumRsName(oneof)}, + {"view_cases", + [&] { + for (int i = 0; i < oneof.field_count(); ++i) { + auto& field = *oneof.field(i); + std::string rs_type = RsTypeNameView(ctx, field); + if (rs_type.empty()) { + continue; + } + ctx.Emit( + { + {"case", OneofCaseRsName(field)}, + {"rs_getter", RsSafeName(field.name())}, + {"type", rs_type}, + }, + R"rs( + $oneof_enum_module$$case_enum_name$::$case$ => + $oneof_enum_module$$view_enum_name$::$case$(self.$rs_getter$()), )rs"); - } - }}, - {"mut_cases", - [&] { - for (int i = 0; i < oneof.field_count(); ++i) { - auto& field = *oneof.field(i); - std::string rs_type = RsTypeNameMut(ctx, field); - if (rs_type.empty()) { - continue; - } - ctx.Emit( - {{"case", OneofCaseRsName(field)}, - {"rs_mut_getter", field.name() + "_mut"}, - {"type", rs_type}}, - // Any extra behavior needed to map the mut getter into the - // unwrapped Mut<>. Right now Message's _mut already returns - // the Mut directly, but for scalars the accessor will return - // an Optional which we then grab the mut by doing - // .try_into_mut().unwrap(). - // - // Note that this unwrap() is safe because the flow is: - // 1) Find out which oneof field is already set (if any) - // 2) If a field is set, call the corresponding field's _mut() - // and wrap the result in the SomeOneofMut enum. - // The unwrap() will only ever panic if the which oneof enum - // disagrees with the corresponding field presence which. - R"rs( - $Msg$_::$case_enum_name$::$case$ => - $Msg$_::$mut_enum_name$::$case$( - self.$rs_mut_getter$().try_into_mut().unwrap()), - )rs"); - } - }}, - {"case_thunk", ThunkName(ctx, oneof, "case")}, - {"getter", - [&] { - ctx.Emit({}, R"rs( - pub fn $oneof_name$($view_self$) -> $Msg$_::$view_enum_name$<$view_lifetime$> { - match unsafe { $case_thunk$(self.raw_msg()) } { - $view_cases$ - _ => $Msg$_::$view_enum_name$::not_set(std::marker::PhantomData) - } - } - )rs"); - }}, - {"getter_mut", - [&] { - if (accessor_case == AccessorCase::VIEW) { - return; - } - ctx.Emit({}, R"rs( - pub fn $oneof_name$_mut(&mut self) -> $Msg$_::$mut_enum_name$ { - match unsafe { $case_thunk$(self.raw_msg()) } { - $mut_cases$ - _ => $Msg$_::$mut_enum_name$::not_set(std::marker::PhantomData) + } + }}, + {"case_thunk", ThunkName(ctx, oneof, "case")}, + }, + R"rs( + pub fn $oneof_name$($self$) -> $oneof_enum_module$$view_enum_name$<$view_lifetime$> { + match $self$.$oneof_name$_case() { + $view_cases$ + _ => $oneof_enum_module$$view_enum_name$::not_set(std::marker::PhantomData) } } - )rs"); - }}}, - R"rs( - $getter$ - $getter_mut$ + + pub fn $oneof_name$_case($self$) -> $oneof_enum_module$$case_enum_name$ { + unsafe { $case_thunk$(self.raw_msg()) } + } )rs"); } void GenerateOneofExternC(Context& ctx, const OneofDescriptor& oneof) { ctx.Emit( { + {"oneof_enum_module", + absl::StrCat("crate::", RustModuleForContainingType( + ctx, oneof.containing_type()))}, {"case_enum_rs_name", OneofCaseEnumRsName(oneof)}, {"case_thunk", ThunkName(ctx, oneof, "case")}, }, R"rs( - fn $case_thunk$(raw_msg: $pbi$::RawMessage) -> $Msg$_::$case_enum_rs_name$; + fn $case_thunk$(raw_msg: $pbi$::RawMessage) -> $oneof_enum_module$$case_enum_rs_name$; )rs"); } diff --git a/src/google/protobuf/cpp_features.pb.cc b/src/google/protobuf/cpp_features.pb.cc index 5f97465e72..a5822da2aa 100644 --- a/src/google/protobuf/cpp_features.pb.cc +++ b/src/google/protobuf/cpp_features.pb.cc @@ -6,6 +6,7 @@ #include "google/protobuf/cpp_features.pb.h" #include +#include #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" @@ -176,6 +177,7 @@ CppFeatures::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_._cached_size_), false, diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 66e3ab2ee1..4573d67089 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -6,6 +6,7 @@ #include "google/protobuf/descriptor.pb.h" #include +#include #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" @@ -1836,7 +1837,7 @@ const char descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto[] AB "ative_int_value\030\005 \001(\003\022\024\n\014double_value\030\006 " "\001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggregate_v" "alue\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part\030\001 \002(" - "\t\022\024\n\014is_extension\030\002 \002(\010\"\255\t\n\nFeatureSet\022|" + "\t\022\024\n\014is_extension\030\002 \002(\010\"\265\t\n\nFeatureSet\022|" "\n\016field_presence\030\001 \001(\0162).google.protobuf" ".FeatureSet.FieldPresenceB9\210\001\001\230\001\004\230\001\001\242\001\r\022" "\010EXPLICIT\030\346\007\242\001\r\022\010IMPLICIT\030\347\007\242\001\r\022\010EXPLICI" @@ -1866,44 +1867,44 @@ const char descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto[] AB "IXED\020\001\022\r\n\tDELIMITED\020\002\"H\n\nJsonFormat\022\027\n\023J" "SON_FORMAT_UNKNOWN\020\000\022\t\n\005ALLOW\020\001\022\026\n\022LEGAC" "Y_BEST_EFFORT\020\002*\006\010\350\007\020\351\007*\006\010\351\007\020\352\007*\006\010\352\007\020\353\007*" - "\006\010\213N\020\220N*\006\010\220N\020\221NJ\006\010\347\007\020\350\007\"\300\002\n\022FeatureSetDe" - "faults\022N\n\010defaults\030\001 \003(\0132<.google.protob" - "uf.FeatureSetDefaults.FeatureSetEditionD" - "efault\0221\n\017minimum_edition\030\004 \001(\0162\030.google" - ".protobuf.Edition\0221\n\017maximum_edition\030\005 \001" - "(\0162\030.google.protobuf.Edition\032t\n\030FeatureS" - "etEditionDefault\022)\n\007edition\030\003 \001(\0162\030.goog" - "le.protobuf.Edition\022-\n\010features\030\002 \001(\0132\033." - "google.protobuf.FeatureSet\"\325\001\n\016SourceCod" - "eInfo\022:\n\010location\030\001 \003(\0132(.google.protobu" - "f.SourceCodeInfo.Location\032\206\001\n\010Location\022\020" - "\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020le" - "ading_comments\030\003 \001(\t\022\031\n\021trailing_comment" - "s\030\004 \001(\t\022!\n\031leading_detached_comments\030\006 \003" - "(\t\"\234\002\n\021GeneratedCodeInfo\022A\n\nannotation\030\001" - " \003(\0132-.google.protobuf.GeneratedCodeInfo" - ".Annotation\032\303\001\n\nAnnotation\022\020\n\004path\030\001 \003(\005" - "B\002\020\001\022\023\n\013source_file\030\002 \001(\t\022\r\n\005begin\030\003 \001(\005" - "\022\013\n\003end\030\004 \001(\005\022H\n\010semantic\030\005 \001(\01626.google" - ".protobuf.GeneratedCodeInfo.Annotation.S" - "emantic\"(\n\010Semantic\022\010\n\004NONE\020\000\022\007\n\003SET\020\001\022\t" - "\n\005ALIAS\020\002*\222\002\n\007Edition\022\023\n\017EDITION_UNKNOWN" - "\020\000\022\023\n\016EDITION_PROTO2\020\346\007\022\023\n\016EDITION_PROTO" - "3\020\347\007\022\021\n\014EDITION_2023\020\350\007\022\021\n\014EDITION_2024\020" - "\351\007\022\027\n\023EDITION_1_TEST_ONLY\020\001\022\027\n\023EDITION_2" - "_TEST_ONLY\020\002\022\035\n\027EDITION_99997_TEST_ONLY\020" - "\235\215\006\022\035\n\027EDITION_99998_TEST_ONLY\020\236\215\006\022\035\n\027ED" - "ITION_99999_TEST_ONLY\020\237\215\006\022\023\n\013EDITION_MAX" - "\020\377\377\377\377\007B~\n\023com.google.protobufB\020Descripto" - "rProtosH\001Z-google.golang.org/protobuf/ty" - "pes/descriptorpb\370\001\001\242\002\003GPB\252\002\032Google.Proto" - "buf.Reflection" + "\006\010\206N\020\207N*\006\010\213N\020\220N*\006\010\220N\020\221NJ\006\010\347\007\020\350\007\"\300\002\n\022Feat" + "ureSetDefaults\022N\n\010defaults\030\001 \003(\0132<.googl" + "e.protobuf.FeatureSetDefaults.FeatureSet" + "EditionDefault\0221\n\017minimum_edition\030\004 \001(\0162" + "\030.google.protobuf.Edition\0221\n\017maximum_edi" + "tion\030\005 \001(\0162\030.google.protobuf.Edition\032t\n\030" + "FeatureSetEditionDefault\022)\n\007edition\030\003 \001(" + "\0162\030.google.protobuf.Edition\022-\n\010features\030" + "\002 \001(\0132\033.google.protobuf.FeatureSet\"\325\001\n\016S" + "ourceCodeInfo\022:\n\010location\030\001 \003(\0132(.google" + ".protobuf.SourceCodeInfo.Location\032\206\001\n\010Lo" + "cation\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002" + "\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031\n\021trailing" + "_comments\030\004 \001(\t\022!\n\031leading_detached_comm" + "ents\030\006 \003(\t\"\234\002\n\021GeneratedCodeInfo\022A\n\nanno" + "tation\030\001 \003(\0132-.google.protobuf.Generated" + "CodeInfo.Annotation\032\303\001\n\nAnnotation\022\020\n\004pa" + "th\030\001 \003(\005B\002\020\001\022\023\n\013source_file\030\002 \001(\t\022\r\n\005beg" + "in\030\003 \001(\005\022\013\n\003end\030\004 \001(\005\022H\n\010semantic\030\005 \001(\0162" + "6.google.protobuf.GeneratedCodeInfo.Anno" + "tation.Semantic\"(\n\010Semantic\022\010\n\004NONE\020\000\022\007\n" + "\003SET\020\001\022\t\n\005ALIAS\020\002*\222\002\n\007Edition\022\023\n\017EDITION" + "_UNKNOWN\020\000\022\023\n\016EDITION_PROTO2\020\346\007\022\023\n\016EDITI" + "ON_PROTO3\020\347\007\022\021\n\014EDITION_2023\020\350\007\022\021\n\014EDITI" + "ON_2024\020\351\007\022\027\n\023EDITION_1_TEST_ONLY\020\001\022\027\n\023E" + "DITION_2_TEST_ONLY\020\002\022\035\n\027EDITION_99997_TE" + "ST_ONLY\020\235\215\006\022\035\n\027EDITION_99998_TEST_ONLY\020\236" + "\215\006\022\035\n\027EDITION_99999_TEST_ONLY\020\237\215\006\022\023\n\013EDI" + "TION_MAX\020\377\377\377\377\007B~\n\023com.google.protobufB\020D" + "escriptorProtosH\001Z-google.golang.org/pro" + "tobuf/types/descriptorpb\370\001\001\242\002\003GPB\252\002\032Goog" + "le.Protobuf.Reflection" }; static ::absl::once_flag descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once; PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto = { false, false, - 9574, + 9582, descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto, "google/protobuf/descriptor.proto", &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, @@ -2383,6 +2384,7 @@ FileDescriptorSet::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(FileDescriptorSet, _impl_._cached_size_), false, @@ -2616,6 +2618,7 @@ FileDescriptorProto::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(FileDescriptorProto, _impl_._cached_size_), false, @@ -3190,6 +3193,7 @@ DescriptorProto_ExtensionRange::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(DescriptorProto_ExtensionRange, _impl_._cached_size_), false, @@ -3452,6 +3456,7 @@ DescriptorProto_ReservedRange::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(DescriptorProto_ReservedRange, _impl_._cached_size_), false, @@ -3710,6 +3715,7 @@ DescriptorProto::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_._cached_size_), false, @@ -4202,6 +4208,7 @@ ExtensionRangeOptions_Declaration::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions_Declaration, _impl_._cached_size_), false, @@ -4535,6 +4542,7 @@ ExtensionRangeOptions::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions, _impl_._cached_size_), false, @@ -4886,6 +4894,7 @@ FieldDescriptorProto::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_._cached_size_), false, @@ -5388,6 +5397,7 @@ OneofDescriptorProto::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(OneofDescriptorProto, _impl_._cached_size_), false, @@ -5629,6 +5639,7 @@ EnumDescriptorProto_EnumReservedRange::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(EnumDescriptorProto_EnumReservedRange, _impl_._cached_size_), false, @@ -5877,6 +5888,7 @@ EnumDescriptorProto::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(EnumDescriptorProto, _impl_._cached_size_), false, @@ -6222,6 +6234,7 @@ EnumValueDescriptorProto::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(EnumValueDescriptorProto, _impl_._cached_size_), false, @@ -6510,6 +6523,7 @@ ServiceDescriptorProto::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(ServiceDescriptorProto, _impl_._cached_size_), false, @@ -6814,6 +6828,7 @@ MethodDescriptorProto::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(MethodDescriptorProto, _impl_._cached_size_), false, @@ -7225,6 +7240,7 @@ FileOptions::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(FileOptions, _impl_._cached_size_), false, @@ -8011,6 +8027,7 @@ MessageOptions::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(MessageOptions, _impl_._cached_size_), false, @@ -8383,6 +8400,7 @@ FieldOptions_EditionDefault::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(FieldOptions_EditionDefault, _impl_._cached_size_), false, @@ -8644,6 +8662,7 @@ FieldOptions::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_._cached_size_), false, @@ -9178,6 +9197,7 @@ OneofOptions::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(OneofOptions, _impl_._cached_size_), false, @@ -9454,6 +9474,7 @@ EnumOptions::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(EnumOptions, _impl_._cached_size_), false, @@ -9804,6 +9825,7 @@ EnumValueOptions::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_._cached_size_), false, @@ -10130,6 +10152,7 @@ ServiceOptions::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(ServiceOptions, _impl_._cached_size_), false, @@ -10437,6 +10460,7 @@ MethodOptions::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(MethodOptions, _impl_._cached_size_), false, @@ -10759,6 +10783,7 @@ UninterpretedOption_NamePart::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(UninterpretedOption_NamePart, _impl_._cached_size_), false, @@ -11019,6 +11044,7 @@ UninterpretedOption::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(UninterpretedOption, _impl_._cached_size_), false, @@ -11404,6 +11430,7 @@ FeatureSet::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_._cached_size_), false, @@ -11755,6 +11782,7 @@ FeatureSetDefaults_FeatureSetEditionDefault::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(FeatureSetDefaults_FeatureSetEditionDefault, _impl_._cached_size_), false, @@ -12013,6 +12041,7 @@ FeatureSetDefaults::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(FeatureSetDefaults, _impl_._cached_size_), false, @@ -12288,6 +12317,7 @@ SourceCodeInfo_Location::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(SourceCodeInfo_Location, _impl_._cached_size_), false, @@ -12615,6 +12645,7 @@ SourceCodeInfo::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(SourceCodeInfo, _impl_._cached_size_), false, @@ -12828,6 +12859,7 @@ GeneratedCodeInfo_Annotation::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _impl_._cached_size_), false, @@ -13147,6 +13179,7 @@ GeneratedCodeInfo::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo, _impl_._cached_size_), false, diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index 6805b9b4b6..cfd2cd4eb1 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -1020,6 +1020,8 @@ message FeatureSet { extensions 1001; // for Protobuf Java extensions 1002; // for Protobuf Go + extensions 9990; // for deprecated Java Proto1 + extensions 9995 to 9999; // For internal testing extensions 10000; // for https://github.com/bufbuild/protobuf-es } diff --git a/src/google/protobuf/descriptor_legacy.h b/src/google/protobuf/descriptor_legacy.h index 88a77b922d..eb1a82988c 100644 --- a/src/google/protobuf/descriptor_legacy.h +++ b/src/google/protobuf/descriptor_legacy.h @@ -1,8 +1,8 @@ #ifndef GOOGLE_PROTOBUF_DESCRIPTOR_EDITION_H__ #define GOOGLE_PROTOBUF_DESCRIPTOR_EDITION_H__ -#include "google/protobuf/descriptor.pb.h" #include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" namespace google { namespace protobuf { diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index 617f729110..ac994cb022 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -7414,7 +7414,8 @@ TEST_F(FeaturesTest, Proto2Features) { const FieldDescriptor* field = message->field(0); const FieldDescriptor* group = message->field(1); EXPECT_THAT(file->options(), EqualsProto("")); - EXPECT_EQ(GetFeatures(file).GetExtension(pb::test).int_file_feature(), -2); + EXPECT_EQ(GetFeatures(file).GetExtension(pb::test).file_feature(), + pb::VALUE1); EXPECT_THAT( GetCoreFeatures(file), EqualsProto(R"pb( field_presence: EXPLICIT @@ -7494,7 +7495,8 @@ TEST_F(FeaturesTest, Proto3Features) { const Descriptor* message = file->message_type(0); const FieldDescriptor* field = message->field(0); EXPECT_THAT(file->options(), EqualsProto("")); - EXPECT_EQ(GetFeatures(file).GetExtension(pb::test).int_file_feature(), -3); + EXPECT_EQ(GetFeatures(file).GetExtension(pb::test).file_feature(), + pb::VALUE2); EXPECT_THAT( GetCoreFeatures(file), EqualsProto(R"pb( field_presence: IMPLICIT @@ -7692,7 +7694,8 @@ TEST_F(FeaturesTest, Edition2023Defaults) { // Since pb::test is registered in the pool, it should end up with defaults in // our FeatureSet. EXPECT_TRUE(GetFeatures(file).HasExtension(pb::test)); - EXPECT_EQ(GetFeatures(file).GetExtension(pb::test).int_file_feature(), 1); + EXPECT_EQ(GetFeatures(file).GetExtension(pb::test).file_feature(), + pb::VALUE3); } TEST_F(FeaturesTest, Edition2024Defaults) { @@ -7718,7 +7721,8 @@ TEST_F(FeaturesTest, Edition2024Defaults) { // Since pb::test is registered in the pool, it should end up with defaults in // our FeatureSet. EXPECT_TRUE(GetFeatures(file).HasExtension(pb::test)); - EXPECT_EQ(GetFeatures(file).GetExtension(pb::test).int_file_feature(), 1); + EXPECT_EQ(GetFeatures(file).GetExtension(pb::test).file_feature(), + pb::VALUE3); } TEST_F(FeaturesBaseTest, DefaultEdition2023Defaults) { @@ -7779,7 +7783,7 @@ TEST_F(FeaturesTest, RestoresOptionsRoundTrip) { options { java_package: "bar" features { - [pb.test] { int_file_feature: 1 } + [pb.test] { file_feature: VALUE3 } } } message_type { @@ -7787,7 +7791,7 @@ TEST_F(FeaturesTest, RestoresOptionsRoundTrip) { options { deprecated: true features { - [pb.test] { int_message_feature: 3 } + [pb.test] { message_feature: VALUE3 } } } field { @@ -7798,7 +7802,7 @@ TEST_F(FeaturesTest, RestoresOptionsRoundTrip) { options { deprecated: true features { - [pb.test] { int_field_feature: 9 } + [pb.test] { field_feature: VALUE9 } } } } @@ -7813,7 +7817,7 @@ TEST_F(FeaturesTest, RestoresOptionsRoundTrip) { name: "foo_oneof" options { features { - [pb.test] { int_oneof_feature: 7 } + [pb.test] { oneof_feature: VALUE7 } } } } @@ -7823,7 +7827,7 @@ TEST_F(FeaturesTest, RestoresOptionsRoundTrip) { options { verification: UNVERIFIED features { - [pb.test] { int_extension_range_feature: 15 } + [pb.test] { extension_range_feature: VALUE15 } } } } @@ -7833,7 +7837,7 @@ TEST_F(FeaturesTest, RestoresOptionsRoundTrip) { options { deprecated: true features { - [pb.test] { int_enum_feature: 4 } + [pb.test] { enum_feature: VALUE4 } } } value { @@ -7842,7 +7846,7 @@ TEST_F(FeaturesTest, RestoresOptionsRoundTrip) { options { deprecated: true features { - [pb.test] { int_enum_entry_feature: 8 } + [pb.test] { enum_entry_feature: VALUE8 } } } } @@ -7852,7 +7856,7 @@ TEST_F(FeaturesTest, RestoresOptionsRoundTrip) { options { deprecated: true features { - [pb.test] { int_service_feature: 11 } + [pb.test] { service_feature: VALUE11 } } } method { @@ -7862,7 +7866,7 @@ TEST_F(FeaturesTest, RestoresOptionsRoundTrip) { options { deprecated: true features { - [pb.test] { int_method_feature: 12 } + [pb.test] { method_feature: VALUE12 } } } } @@ -7873,46 +7877,46 @@ TEST_F(FeaturesTest, RestoresOptionsRoundTrip) { EXPECT_THAT(proto.options(), EqualsProto(R"pb(java_package: 'bar' features { - [pb.test] { int_file_feature: 1 } + [pb.test] { file_feature: VALUE3 } })pb")); EXPECT_THAT(proto.message_type(0).options(), EqualsProto(R"pb(deprecated: true features { - [pb.test] { int_message_feature: 3 } + [pb.test] { message_feature: VALUE3 } })pb")); EXPECT_THAT(proto.message_type(0).field(0).options(), EqualsProto(R"pb(deprecated: true features { - [pb.test] { int_field_feature: 9 } + [pb.test] { field_feature: VALUE9 } })pb")); EXPECT_THAT(proto.message_type(0).oneof_decl(0).options(), EqualsProto(R"pb(features { - [pb.test] { int_oneof_feature: 7 } + [pb.test] { oneof_feature: VALUE7 } })pb")); EXPECT_THAT(proto.message_type(0).extension_range(0).options(), EqualsProto(R"pb(verification: UNVERIFIED features { - [pb.test] { int_extension_range_feature: 15 } + [pb.test] { extension_range_feature: VALUE15 } })pb")); EXPECT_THAT(proto.enum_type(0).options(), EqualsProto(R"pb(deprecated: true features { - [pb.test] { int_enum_feature: 4 } + [pb.test] { enum_feature: VALUE4 } })pb")); EXPECT_THAT(proto.enum_type(0).value(0).options(), EqualsProto(R"pb(deprecated: true features { - [pb.test] { int_enum_entry_feature: 8 } + [pb.test] { enum_entry_feature: VALUE8 } })pb")); EXPECT_THAT(proto.service(0).options(), EqualsProto(R"pb(deprecated: true features { - [pb.test] { int_service_feature: 11 } + [pb.test] { service_feature: VALUE11 } })pb")); EXPECT_THAT(proto.service(0).method(0).options(), EqualsProto(R"pb(deprecated: true features { - [pb.test] { int_method_feature: 12 } + [pb.test] { method_feature: VALUE12 } })pb")); } @@ -7999,9 +8003,9 @@ TEST_F(FeaturesTest, ReusesFeaturesExtension) { edition: EDITION_2023 options { features { - [pb.TestMessage.test_message] { int_file_feature: 8 } - [pb.TestMessage.Nested.test_nested] { int_file_feature: 7 } - [pb.test] { int_file_feature: 9 } + [pb.TestMessage.test_message] { file_feature: VALUE6 } + [pb.TestMessage.Nested.test_nested] { file_feature: VALUE5 } + [pb.test] { file_feature: VALUE7 } } } )pb"); @@ -8011,9 +8015,9 @@ TEST_F(FeaturesTest, ReusesFeaturesExtension) { edition: EDITION_2023 options { features { - [pb.test] { int_file_feature: 9 } - [pb.TestMessage.test_message] { int_file_feature: 8 } - [pb.TestMessage.Nested.test_nested] { int_file_feature: 7 } + [pb.test] { file_feature: VALUE7 } + [pb.TestMessage.test_message] { file_feature: VALUE6 } + [pb.TestMessage.Nested.test_nested] { file_feature: VALUE5 } } } )pb"); @@ -8176,15 +8180,16 @@ TEST_F(FeaturesTest, FileFeaturesExtension) { EXPECT_THAT(file->options(), EqualsProto("")); EXPECT_EQ(GetFeatures(file).field_presence(), FeatureSet::IMPLICIT); EXPECT_EQ(GetFeatures(file).enum_type(), FeatureSet::OPEN); - EXPECT_EQ(GetFeatures(file).GetExtension(pb::test).int_file_feature(), 3); + EXPECT_EQ(GetFeatures(file).GetExtension(pb::test).file_feature(), + pb::VALUE5); EXPECT_EQ(GetFeatures(file) .GetExtension(pb::TestMessage::test_message) - .int_file_feature(), - 3); + .file_feature(), + pb::VALUE5); EXPECT_EQ(GetFeatures(file) .GetExtension(pb::TestMessage::Nested::test_nested) - .int_file_feature(), - 3); + .file_feature(), + pb::VALUE5); } TEST_F(FeaturesTest, FileFeaturesExtensionOverride) { @@ -8198,24 +8203,25 @@ TEST_F(FeaturesTest, FileFeaturesExtensionOverride) { options { features { field_presence: IMPLICIT - [pb.test] { int_file_feature: 9 } - [pb.TestMessage.test_message] { int_file_feature: 8 } - [pb.TestMessage.Nested.test_nested] { int_file_feature: 7 } + [pb.test] { file_feature: VALUE7 } + [pb.TestMessage.test_message] { file_feature: VALUE6 } + [pb.TestMessage.Nested.test_nested] { file_feature: VALUE5 } } } )pb"); EXPECT_THAT(file->options(), EqualsProto("")); EXPECT_EQ(GetFeatures(file).field_presence(), FeatureSet::IMPLICIT); EXPECT_EQ(GetFeatures(file).enum_type(), FeatureSet::OPEN); - EXPECT_EQ(GetFeatures(file).GetExtension(pb::test).int_file_feature(), 9); + EXPECT_EQ(GetFeatures(file).GetExtension(pb::test).file_feature(), + pb::VALUE7); EXPECT_EQ(GetFeatures(file) .GetExtension(pb::TestMessage::test_message) - .int_file_feature(), - 8); + .file_feature(), + pb::VALUE6); EXPECT_EQ(GetFeatures(file) .GetExtension(pb::TestMessage::Nested::test_nested) - .int_file_feature(), - 7); + .file_feature(), + pb::VALUE5); } TEST_F(FeaturesTest, MessageFeaturesDefault) { @@ -8263,22 +8269,22 @@ TEST_F(FeaturesTest, MessageFeaturesOverride) { dependency: "google/protobuf/unittest_features.proto" options { features { - [pb.test] { int_multiple_feature: 2 } + [pb.test] { multiple_feature: VALUE2 } } } message_type { name: "Foo" options { features { - [pb.test] { int_multiple_feature: 9 } + [pb.test] { multiple_feature: VALUE9 } } } } )pb"); const Descriptor* message = file->message_type(0); EXPECT_THAT(message->options(), EqualsProto("")); - EXPECT_EQ(GetFeatures(message).GetExtension(pb::test).int_multiple_feature(), - 9); + EXPECT_EQ(GetFeatures(message).GetExtension(pb::test).multiple_feature(), + pb::VALUE9); } TEST_F(FeaturesTest, NestedMessageFeaturesOverride) { @@ -8291,21 +8297,21 @@ TEST_F(FeaturesTest, NestedMessageFeaturesOverride) { dependency: "google/protobuf/unittest_features.proto" options { features { - [pb.test] { int_multiple_feature: 2 int_file_feature: 9 } + [pb.test] { multiple_feature: VALUE2 file_feature: VALUE7 } } } message_type { name: "Foo" options { features { - [pb.test] { int_multiple_feature: 10 int_message_feature: 3 } + [pb.test] { multiple_feature: VALUE10 message_feature: VALUE3 } } } nested_type { name: "Bar" options { features { - [pb.test] { int_multiple_feature: 5 } + [pb.test] { multiple_feature: VALUE5 } } } } @@ -8313,12 +8319,14 @@ TEST_F(FeaturesTest, NestedMessageFeaturesOverride) { )pb"); const Descriptor* message = file->message_type(0)->nested_type(0); EXPECT_THAT(message->options(), EqualsProto("")); - EXPECT_EQ(GetFeatures(message).GetExtension(pb::test).int_field_feature(), 1); - EXPECT_EQ(GetFeatures(message).GetExtension(pb::test).int_multiple_feature(), - 5); - EXPECT_EQ(GetFeatures(message).GetExtension(pb::test).int_file_feature(), 9); - EXPECT_EQ(GetFeatures(message).GetExtension(pb::test).int_message_feature(), - 3); + EXPECT_EQ(GetFeatures(message).GetExtension(pb::test).field_feature(), + pb::VALUE1); + EXPECT_EQ(GetFeatures(message).GetExtension(pb::test).multiple_feature(), + pb::VALUE5); + EXPECT_EQ(GetFeatures(message).GetExtension(pb::test).file_feature(), + pb::VALUE7); + EXPECT_EQ(GetFeatures(message).GetExtension(pb::test).message_feature(), + pb::VALUE3); } TEST_F(FeaturesTest, FieldFeaturesDefault) { @@ -8356,14 +8364,14 @@ TEST_F(FeaturesTest, FieldFeaturesInherit) { options { features { field_presence: IMPLICIT - [pb.test] { int_multiple_feature: 1 } + [pb.test] { multiple_feature: VALUE1 } } } message_type { name: "Foo" options { features { - [pb.test] { int_multiple_feature: 9 } + [pb.test] { multiple_feature: VALUE9 } } } field { name: "bar" number: 1 label: LABEL_REPEATED type: TYPE_INT64 } @@ -8372,8 +8380,8 @@ TEST_F(FeaturesTest, FieldFeaturesInherit) { const FieldDescriptor* field = file->message_type(0)->field(0); EXPECT_THAT(field->options(), EqualsProto("")); EXPECT_EQ(GetFeatures(field).field_presence(), FeatureSet::IMPLICIT); - EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).int_multiple_feature(), - 9); + EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).multiple_feature(), + pb::VALUE9); } TEST_F(FeaturesTest, FieldFeaturesOverride) { @@ -8388,14 +8396,14 @@ TEST_F(FeaturesTest, FieldFeaturesOverride) { features { enum_type: CLOSED field_presence: IMPLICIT - [pb.test] { int_multiple_feature: 2 } + [pb.test] { multiple_feature: VALUE2 } } } message_type { name: "Foo" options { features { - [pb.test] { int_multiple_feature: 3 } + [pb.test] { multiple_feature: VALUE3 } } } field { @@ -8406,7 +8414,7 @@ TEST_F(FeaturesTest, FieldFeaturesOverride) { options { features { field_presence: EXPLICIT - [pb.test] { int_multiple_feature: 9 } + [pb.test] { multiple_feature: VALUE9 } } } } @@ -8416,8 +8424,8 @@ TEST_F(FeaturesTest, FieldFeaturesOverride) { EXPECT_THAT(field->options(), EqualsProto("")); EXPECT_EQ(GetFeatures(field).field_presence(), FeatureSet::EXPLICIT); EXPECT_EQ(GetFeatures(field).enum_type(), FeatureSet::CLOSED); - EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).int_multiple_feature(), - 9); + EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).multiple_feature(), + pb::VALUE9); } TEST_F(FeaturesTest, OneofFieldFeaturesInherit) { @@ -8431,14 +8439,14 @@ TEST_F(FeaturesTest, OneofFieldFeaturesInherit) { options { features { field_presence: IMPLICIT - [pb.test] { int_multiple_feature: 1 } + [pb.test] { multiple_feature: VALUE1 } } } message_type { name: "Foo" options { features { - [pb.test] { int_multiple_feature: 6 } + [pb.test] { multiple_feature: VALUE6 } } } field { @@ -8452,7 +8460,7 @@ TEST_F(FeaturesTest, OneofFieldFeaturesInherit) { name: "foo_oneof" options { features { - [pb.test] { int_multiple_feature: 9 } + [pb.test] { multiple_feature: VALUE9 } } } } @@ -8461,8 +8469,8 @@ TEST_F(FeaturesTest, OneofFieldFeaturesInherit) { const FieldDescriptor* field = file->message_type(0)->field(0); EXPECT_THAT(field->options(), EqualsProto("")); EXPECT_EQ(GetFeatures(field).field_presence(), FeatureSet::IMPLICIT); - EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).int_multiple_feature(), - 9); + EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).multiple_feature(), + pb::VALUE9); } TEST_F(FeaturesTest, OneofFieldFeaturesOverride) { @@ -8475,14 +8483,14 @@ TEST_F(FeaturesTest, OneofFieldFeaturesOverride) { dependency: "google/protobuf/unittest_features.proto" options { features { - [pb.test] { int_multiple_feature: 2 int_file_feature: 2 } + [pb.test] { multiple_feature: VALUE2 file_feature: VALUE4 } } } message_type { name: "Foo" options { features { - [pb.test] { int_multiple_feature: 3 int_message_feature: 3 } + [pb.test] { multiple_feature: VALUE3 message_feature: VALUE3 } } } field { @@ -8492,7 +8500,7 @@ TEST_F(FeaturesTest, OneofFieldFeaturesOverride) { type: TYPE_STRING options { features { - [pb.test] { int_multiple_feature: 9 } + [pb.test] { multiple_feature: VALUE9 } } } oneof_index: 0 @@ -8501,7 +8509,7 @@ TEST_F(FeaturesTest, OneofFieldFeaturesOverride) { name: "foo_oneof" options { features { - [pb.test] { int_multiple_feature: 6 int_oneof_feature: 6 } + [pb.test] { multiple_feature: VALUE6 oneof_feature: VALUE6 } } } } @@ -8509,11 +8517,14 @@ TEST_F(FeaturesTest, OneofFieldFeaturesOverride) { )pb"); const FieldDescriptor* field = file->message_type(0)->field(0); EXPECT_THAT(field->options(), EqualsProto("")); - EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).int_multiple_feature(), - 9); - EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).int_oneof_feature(), 6); - EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).int_message_feature(), 3); - EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).int_file_feature(), 2); + EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).multiple_feature(), + pb::VALUE9); + EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).oneof_feature(), + pb::VALUE6); + EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).message_feature(), + pb::VALUE3); + EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).file_feature(), + pb::VALUE4); } TEST_F(FeaturesTest, MapFieldFeaturesOverride) { @@ -8522,16 +8533,16 @@ TEST_F(FeaturesTest, MapFieldFeaturesOverride) { import "google/protobuf/unittest_features.proto"; - option features.(pb.test).int_file_feature = 99; - option features.(pb.test).int_multiple_feature = 1; + option features.(pb.test).file_feature = VALUE7; + option features.(pb.test).multiple_feature = VALUE1; message Foo { - option features.(pb.test).int_message_feature = 87; - option features.(pb.test).int_multiple_feature = 2; + option features.(pb.test).message_feature = VALUE8; + option features.(pb.test).multiple_feature = VALUE2; map map_field = 1 [ - features.(pb.test).int_field_feature = 100, - features.(pb.test).int_multiple_feature = 3 + features.(pb.test).field_feature = VALUE10, + features.(pb.test).multiple_feature = VALUE3 ]; } )schema"; @@ -8557,15 +8568,17 @@ TEST_F(FeaturesTest, MapFieldFeaturesOverride) { const FieldDescriptor* value = map_field->message_type()->field(1); auto validate = [](const FieldDescriptor* desc) { - EXPECT_EQ(GetFeatures(desc).GetExtension(pb::test).int_file_feature(), 99) + EXPECT_EQ(GetFeatures(desc).GetExtension(pb::test).file_feature(), + pb::VALUE7) << desc->DebugString(); - EXPECT_EQ(GetFeatures(desc).GetExtension(pb::test).int_message_feature(), - 87) + EXPECT_EQ(GetFeatures(desc).GetExtension(pb::test).message_feature(), + pb::VALUE8) << desc->DebugString(); - EXPECT_EQ(GetFeatures(desc).GetExtension(pb::test).int_field_feature(), 100) + EXPECT_EQ(GetFeatures(desc).GetExtension(pb::test).field_feature(), + pb::VALUE10) << desc->DebugString(); - EXPECT_EQ(GetFeatures(desc).GetExtension(pb::test).int_multiple_feature(), - 3) + EXPECT_EQ(GetFeatures(desc).GetExtension(pb::test).multiple_feature(), + pb::VALUE3) << desc->DebugString(); }; @@ -8632,7 +8645,7 @@ TEST_F(FeaturesTest, RootExtensionFeaturesOverride) { features { enum_type: CLOSED field_presence: IMPLICIT - [pb.test] { int_multiple_feature: 2 } + [pb.test] { multiple_feature: VALUE2 } } } extension { @@ -8643,7 +8656,7 @@ TEST_F(FeaturesTest, RootExtensionFeaturesOverride) { options { features { enum_type: OPEN - [pb.test] { int_multiple_feature: 9 } + [pb.test] { multiple_feature: VALUE9 } } } extendee: "Foo" @@ -8657,8 +8670,8 @@ TEST_F(FeaturesTest, RootExtensionFeaturesOverride) { EXPECT_THAT(field->options(), EqualsProto("")); EXPECT_EQ(GetFeatures(field).field_presence(), FeatureSet::IMPLICIT); EXPECT_EQ(GetFeatures(field).enum_type(), FeatureSet::OPEN); - EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).int_multiple_feature(), - 9); + EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).multiple_feature(), + pb::VALUE9); } TEST_F(FeaturesTest, MessageExtensionFeaturesOverride) { @@ -8673,14 +8686,14 @@ TEST_F(FeaturesTest, MessageExtensionFeaturesOverride) { features { enum_type: CLOSED field_presence: IMPLICIT - [pb.test] { int_multiple_feature: 2 } + [pb.test] { multiple_feature: VALUE2 } } } message_type { name: "Foo" options { features { - [pb.test] { int_multiple_feature: 3 } + [pb.test] { multiple_feature: VALUE3 } } } extension { @@ -8697,7 +8710,7 @@ TEST_F(FeaturesTest, MessageExtensionFeaturesOverride) { extension_range { start: 1 end: 2 } options { features { - [pb.test] { int_multiple_feature: 7 } + [pb.test] { multiple_feature: VALUE7 } } } } @@ -8706,8 +8719,8 @@ TEST_F(FeaturesTest, MessageExtensionFeaturesOverride) { EXPECT_THAT(field->options(), EqualsProto("")); EXPECT_EQ(GetFeatures(field).field_presence(), FeatureSet::IMPLICIT); EXPECT_EQ(GetFeatures(field).enum_type(), FeatureSet::OPEN); - EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).int_multiple_feature(), - 3); + EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).multiple_feature(), + pb::VALUE3); } TEST_F(FeaturesTest, EnumFeaturesDefault) { @@ -8761,14 +8774,14 @@ TEST_F(FeaturesTest, EnumFeaturesOverride) { dependency: "google/protobuf/unittest_features.proto" options { features { - [pb.test] { int_multiple_feature: 2 } + [pb.test] { multiple_feature: VALUE2 } } } enum_type { name: "Foo" options { features { - [pb.test] { int_multiple_feature: 9 } + [pb.test] { multiple_feature: VALUE9 } } } value { name: "BAR" number: 0 } @@ -8776,7 +8789,8 @@ TEST_F(FeaturesTest, EnumFeaturesOverride) { )pb"); const EnumDescriptor* enm = file->enum_type(0); EXPECT_THAT(enm->options(), EqualsProto("")); - EXPECT_EQ(GetFeatures(enm).GetExtension(pb::test).int_multiple_feature(), 9); + EXPECT_EQ(GetFeatures(enm).GetExtension(pb::test).multiple_feature(), + pb::VALUE9); } TEST_F(FeaturesTest, NestedEnumFeatures) { @@ -8789,21 +8803,21 @@ TEST_F(FeaturesTest, NestedEnumFeatures) { dependency: "google/protobuf/unittest_features.proto" options { features { - [pb.test] { int_multiple_feature: 2 int_file_feature: 9 } + [pb.test] { multiple_feature: VALUE2 file_feature: VALUE7 } } } message_type { name: "Foo" options { features { - [pb.test] { int_multiple_feature: 10 int_message_feature: 3 } + [pb.test] { multiple_feature: VALUE10 message_feature: VALUE3 } } } enum_type { name: "Bar" options { features { - [pb.test] { int_multiple_feature: 5 } + [pb.test] { multiple_feature: VALUE5 } } } value { name: "BAR" number: 0 } @@ -8812,10 +8826,13 @@ TEST_F(FeaturesTest, NestedEnumFeatures) { )pb"); const EnumDescriptor* enm = file->message_type(0)->enum_type(0); EXPECT_THAT(enm->options(), EqualsProto("")); - EXPECT_EQ(GetFeatures(enm).GetExtension(pb::test).int_field_feature(), 1); - EXPECT_EQ(GetFeatures(enm).GetExtension(pb::test).int_multiple_feature(), 5); - EXPECT_EQ(GetFeatures(enm).GetExtension(pb::test).int_file_feature(), 9); - EXPECT_EQ(GetFeatures(enm).GetExtension(pb::test).int_message_feature(), 3); + EXPECT_EQ(GetFeatures(enm).GetExtension(pb::test).field_feature(), + pb::VALUE1); + EXPECT_EQ(GetFeatures(enm).GetExtension(pb::test).multiple_feature(), + pb::VALUE5); + EXPECT_EQ(GetFeatures(enm).GetExtension(pb::test).file_feature(), pb::VALUE7); + EXPECT_EQ(GetFeatures(enm).GetExtension(pb::test).message_feature(), + pb::VALUE3); } TEST_F(FeaturesTest, EnumValueFeaturesDefault) { @@ -8853,7 +8870,7 @@ TEST_F(FeaturesTest, EnumValueFeaturesInherit) { name: "Foo" options { features { - [pb.test] { int_enum_feature: 9 } + [pb.test] { enum_feature: VALUE9 } } } value { name: "BAR" number: 0 } @@ -8862,7 +8879,8 @@ TEST_F(FeaturesTest, EnumValueFeaturesInherit) { const EnumValueDescriptor* value = file->enum_type(0)->value(0); EXPECT_THAT(value->options(), EqualsProto("")); EXPECT_EQ(GetFeatures(value).enum_type(), FeatureSet::CLOSED); - EXPECT_EQ(GetFeatures(value).GetExtension(pb::test).int_enum_feature(), 9); + EXPECT_EQ(GetFeatures(value).GetExtension(pb::test).enum_feature(), + pb::VALUE9); } TEST_F(FeaturesTest, EnumValueFeaturesOverride) { @@ -8875,14 +8893,14 @@ TEST_F(FeaturesTest, EnumValueFeaturesOverride) { dependency: "google/protobuf/unittest_features.proto" options { features { - [pb.test] { int_multiple_feature: 7 } + [pb.test] { multiple_feature: VALUE7 } } } enum_type { name: "Foo" options { features { - [pb.test] { int_multiple_feature: 8 } + [pb.test] { multiple_feature: VALUE8 } } } value { @@ -8890,7 +8908,7 @@ TEST_F(FeaturesTest, EnumValueFeaturesOverride) { number: 0 options { features { - [pb.test] { int_multiple_feature: 9 int_enum_entry_feature: 87 } + [pb.test] { multiple_feature: VALUE9 enum_entry_feature: VALUE8 } } } } @@ -8898,10 +8916,10 @@ TEST_F(FeaturesTest, EnumValueFeaturesOverride) { )pb"); const EnumValueDescriptor* value = file->enum_type(0)->value(0); EXPECT_THAT(value->options(), EqualsProto("")); - EXPECT_EQ(GetFeatures(value).GetExtension(pb::test).int_multiple_feature(), - 9); - EXPECT_EQ(GetFeatures(value).GetExtension(pb::test).int_enum_entry_feature(), - 87); + EXPECT_EQ(GetFeatures(value).GetExtension(pb::test).multiple_feature(), + pb::VALUE9); + EXPECT_EQ(GetFeatures(value).GetExtension(pb::test).enum_entry_feature(), + pb::VALUE8); } TEST_F(FeaturesTest, OneofFeaturesDefault) { @@ -8954,7 +8972,7 @@ TEST_F(FeaturesTest, OneofFeaturesInherit) { oneof_decl { name: "foo_oneof" } options { features { - [pb.test] { int_message_feature: 9 } + [pb.test] { message_feature: VALUE9 } } } } @@ -8962,7 +8980,8 @@ TEST_F(FeaturesTest, OneofFeaturesInherit) { const OneofDescriptor* oneof = file->message_type(0)->oneof_decl(0); EXPECT_THAT(oneof->options(), EqualsProto("")); EXPECT_EQ(GetFeatures(oneof).enum_type(), FeatureSet::CLOSED); - EXPECT_EQ(GetFeatures(oneof).GetExtension(pb::test).int_message_feature(), 9); + EXPECT_EQ(GetFeatures(oneof).GetExtension(pb::test).message_feature(), + pb::VALUE9); } TEST_F(FeaturesTest, OneofFeaturesOverride) { @@ -8975,7 +8994,7 @@ TEST_F(FeaturesTest, OneofFeaturesOverride) { dependency: "google/protobuf/unittest_features.proto" options { features { - [pb.test] { int_multiple_feature: 2 int_file_feature: 2 } + [pb.test] { multiple_feature: VALUE2 file_feature: VALUE4 } } } message_type { @@ -8991,23 +9010,25 @@ TEST_F(FeaturesTest, OneofFeaturesOverride) { name: "foo_oneof" options { features { - [pb.test] { int_multiple_feature: 9 } + [pb.test] { multiple_feature: VALUE9 } } } } options { features { - [pb.test] { int_multiple_feature: 5 int_message_feature: 5 } + [pb.test] { multiple_feature: VALUE5 message_feature: VALUE5 } } } } )pb"); const OneofDescriptor* oneof = file->message_type(0)->oneof_decl(0); EXPECT_THAT(oneof->options(), EqualsProto("")); - EXPECT_EQ(GetFeatures(oneof).GetExtension(pb::test).int_multiple_feature(), - 9); - EXPECT_EQ(GetFeatures(oneof).GetExtension(pb::test).int_message_feature(), 5); - EXPECT_EQ(GetFeatures(oneof).GetExtension(pb::test).int_file_feature(), 2); + EXPECT_EQ(GetFeatures(oneof).GetExtension(pb::test).multiple_feature(), + pb::VALUE9); + EXPECT_EQ(GetFeatures(oneof).GetExtension(pb::test).message_feature(), + pb::VALUE5); + EXPECT_EQ(GetFeatures(oneof).GetExtension(pb::test).file_feature(), + pb::VALUE4); } TEST_F(FeaturesTest, ExtensionRangeFeaturesDefault) { @@ -9046,7 +9067,7 @@ TEST_F(FeaturesTest, ExtensionRangeFeaturesInherit) { name: "Foo" options { features { - [pb.test] { int_message_feature: 9 } + [pb.test] { message_feature: VALUE9 } } } extension_range { start: 1 end: 100 } @@ -9056,7 +9077,8 @@ TEST_F(FeaturesTest, ExtensionRangeFeaturesInherit) { file->message_type(0)->extension_range(0); EXPECT_THAT(range->options(), EqualsProto("")); EXPECT_EQ(GetFeatures(range).enum_type(), FeatureSet::CLOSED); - EXPECT_EQ(GetFeatures(range).GetExtension(pb::test).int_message_feature(), 9); + EXPECT_EQ(GetFeatures(range).GetExtension(pb::test).message_feature(), + pb::VALUE9); } TEST_F(FeaturesTest, ExtensionRangeFeaturesOverride) { @@ -9069,14 +9091,14 @@ TEST_F(FeaturesTest, ExtensionRangeFeaturesOverride) { dependency: "google/protobuf/unittest_features.proto" options { features { - [pb.test] { int_multiple_feature: 2 int_file_feature: 2 } + [pb.test] { multiple_feature: VALUE2 file_feature: VALUE4 } } } message_type { name: "Foo" options { features { - [pb.test] { int_multiple_feature: 5 int_message_feature: 5 } + [pb.test] { multiple_feature: VALUE5 message_feature: VALUE5 } } } extension_range { @@ -9084,7 +9106,7 @@ TEST_F(FeaturesTest, ExtensionRangeFeaturesOverride) { end: 100 options { features { - [pb.test] { int_multiple_feature: 9 } + [pb.test] { multiple_feature: VALUE9 } } } } @@ -9093,10 +9115,12 @@ TEST_F(FeaturesTest, ExtensionRangeFeaturesOverride) { const Descriptor::ExtensionRange* range = file->message_type(0)->extension_range(0); EXPECT_THAT(range->options(), EqualsProto("")); - EXPECT_EQ(GetFeatures(range).GetExtension(pb::test).int_multiple_feature(), - 9); - EXPECT_EQ(GetFeatures(range).GetExtension(pb::test).int_message_feature(), 5); - EXPECT_EQ(GetFeatures(range).GetExtension(pb::test).int_file_feature(), 2); + EXPECT_EQ(GetFeatures(range).GetExtension(pb::test).multiple_feature(), + pb::VALUE9); + EXPECT_EQ(GetFeatures(range).GetExtension(pb::test).message_feature(), + pb::VALUE5); + EXPECT_EQ(GetFeatures(range).GetExtension(pb::test).file_feature(), + pb::VALUE4); } TEST_F(FeaturesTest, ServiceFeaturesDefault) { @@ -9144,22 +9168,22 @@ TEST_F(FeaturesTest, ServiceFeaturesOverride) { dependency: "google/protobuf/unittest_features.proto" options { features { - [pb.test] { int_multiple_feature: 2 } + [pb.test] { multiple_feature: VALUE2 } } } service { name: "Foo" options { features { - [pb.test] { int_multiple_feature: 9 } + [pb.test] { multiple_feature: VALUE9 } } } } )pb"); const ServiceDescriptor* service = file->service(0); EXPECT_THAT(service->options(), EqualsProto("")); - EXPECT_EQ(GetFeatures(service).GetExtension(pb::test).int_multiple_feature(), - 9); + EXPECT_EQ(GetFeatures(service).GetExtension(pb::test).multiple_feature(), + pb::VALUE9); } TEST_F(FeaturesTest, MethodFeaturesDefault) { @@ -9201,7 +9225,7 @@ TEST_F(FeaturesTest, MethodFeaturesInherit) { name: "Foo" options { features { - [pb.test] { int_service_feature: 9 } + [pb.test] { service_feature: VALUE9 } } } method { name: "Bar" input_type: "EmptyMsg" output_type: "EmptyMsg" } @@ -9210,8 +9234,8 @@ TEST_F(FeaturesTest, MethodFeaturesInherit) { const MethodDescriptor* method = file->service(0)->method(0); EXPECT_THAT(method->options(), EqualsProto("")); EXPECT_EQ(GetFeatures(method).enum_type(), FeatureSet::CLOSED); - EXPECT_EQ(GetFeatures(method).GetExtension(pb::test).int_service_feature(), - 9); + EXPECT_EQ(GetFeatures(method).GetExtension(pb::test).service_feature(), + pb::VALUE9); } TEST_F(FeaturesTest, MethodFeaturesOverride) { @@ -9226,14 +9250,14 @@ TEST_F(FeaturesTest, MethodFeaturesOverride) { options { features { enum_type: CLOSED - [pb.test] { int_multiple_feature: 2 } + [pb.test] { multiple_feature: VALUE2 } } } service { name: "Foo" options { features { - [pb.test] { int_service_feature: 4 int_multiple_feature: 4 } + [pb.test] { service_feature: VALUE4 multiple_feature: VALUE4 } } } method { @@ -9242,7 +9266,7 @@ TEST_F(FeaturesTest, MethodFeaturesOverride) { output_type: "EmptyMsg" options { features { - [pb.test] { int_multiple_feature: 9 } + [pb.test] { multiple_feature: VALUE9 } } } } @@ -9251,10 +9275,10 @@ TEST_F(FeaturesTest, MethodFeaturesOverride) { const MethodDescriptor* method = file->service(0)->method(0); EXPECT_THAT(method->options(), EqualsProto("")); EXPECT_EQ(GetFeatures(method).enum_type(), FeatureSet::CLOSED); - EXPECT_EQ(GetFeatures(method).GetExtension(pb::test).int_service_feature(), - 4); - EXPECT_EQ(GetFeatures(method).GetExtension(pb::test).int_multiple_feature(), - 9); + EXPECT_EQ(GetFeatures(method).GetExtension(pb::test).service_feature(), + pb::VALUE4); + EXPECT_EQ(GetFeatures(method).GetExtension(pb::test).multiple_feature(), + pb::VALUE9); } TEST_F(FeaturesTest, FieldFeatureHelpers) { @@ -9991,7 +10015,7 @@ TEST_F(FeaturesTest, CopyToIncludesFeatures) { name: "Foo" options { features { - [pb.test] { int_multiple_feature: 9 } + [pb.test] { multiple_feature: VALUE9 } } } field { @@ -10010,7 +10034,7 @@ TEST_F(FeaturesTest, CopyToIncludesFeatures) { features { field_presence: IMPLICIT })pb")); EXPECT_THAT(proto.message_type(0).options(), EqualsProto(R"pb(features { - [pb.test] { int_multiple_feature: 9 } + [pb.test] { multiple_feature: VALUE9 } })pb")); EXPECT_THAT( proto.message_type(0).field(0).options(), @@ -10092,14 +10116,14 @@ TEST_F(FeaturesTest, UninterpretedOptionsMergeExtension) { uninterpreted_option { name { name_part: "features" is_extension: false } name { name_part: "pb.test" is_extension: true } - name { name_part: "int_multiple_feature" is_extension: false } - positive_int_value: 5 + name { name_part: "multiple_feature" is_extension: false } + identifier_value: "VALUE5" } uninterpreted_option { name { name_part: "features" is_extension: false } name { name_part: "pb.test" is_extension: true } - name { name_part: "int_file_feature" is_extension: false } - positive_int_value: 5 + name { name_part: "file_feature" is_extension: false } + identifier_value: "VALUE5" } } message_type { @@ -10108,14 +10132,14 @@ TEST_F(FeaturesTest, UninterpretedOptionsMergeExtension) { uninterpreted_option { name { name_part: "features" is_extension: false } name { name_part: "pb.test" is_extension: true } - name { name_part: "int_multiple_feature" is_extension: false } - positive_int_value: 7 + name { name_part: "multiple_feature" is_extension: false } + identifier_value: "VALUE6" } uninterpreted_option { name { name_part: "features" is_extension: false } name { name_part: "pb.test" is_extension: true } - name { name_part: "int_message_feature" is_extension: false } - positive_int_value: 7 + name { name_part: "message_feature" is_extension: false } + identifier_value: "VALUE6" } } field { @@ -10127,14 +10151,14 @@ TEST_F(FeaturesTest, UninterpretedOptionsMergeExtension) { uninterpreted_option { name { name_part: "features" is_extension: false } name { name_part: "pb.test" is_extension: true } - name { name_part: "int_multiple_feature" is_extension: false } - positive_int_value: 9 + name { name_part: "multiple_feature" is_extension: false } + identifier_value: "VALUE7" } uninterpreted_option { name { name_part: "features" is_extension: false } name { name_part: "pb.test" is_extension: true } - name { name_part: "int_field_feature" is_extension: false } - positive_int_value: 9 + name { name_part: "field_feature" is_extension: false } + identifier_value: "VALUE7" } } } @@ -10142,11 +10166,14 @@ TEST_F(FeaturesTest, UninterpretedOptionsMergeExtension) { )pb"); const FieldDescriptor* field = file->message_type(0)->field(0); EXPECT_THAT(field->options(), EqualsProto("")); - EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).int_file_feature(), 5); - EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).int_message_feature(), 7); - EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).int_field_feature(), 9); - EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).int_multiple_feature(), - 9); + EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).file_feature(), + pb::VALUE5); + EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).message_feature(), + pb::VALUE6); + EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).field_feature(), + pb::VALUE7); + EXPECT_EQ(GetFeatures(field).GetExtension(pb::test).multiple_feature(), + pb::VALUE7); } TEST_F(FeaturesTest, InvalidJsonUniquenessDefaultWarning) { @@ -10343,7 +10370,7 @@ INSTANTIATE_TEST_SUITE_P( dependency: "google/protobuf/unittest_features.proto" options { features { - [pb.test] { int_file_feature: 1 } + [pb.test] { file_feature: VALUE3 } } } )pb"), @@ -10438,7 +10465,7 @@ INSTANTIATE_TEST_SUITE_P( name: "foo_oneof" options { features { - [pb.test] { int_oneof_feature: 7 } + [pb.test] { oneof_feature: VALUE7 } } } } @@ -10456,7 +10483,7 @@ INSTANTIATE_TEST_SUITE_P( end: 100 options { features { - [pb.test] { int_extension_range_feature: 15 } + [pb.test] { extension_range_feature: VALUE15 } } } } @@ -10485,7 +10512,7 @@ INSTANTIATE_TEST_SUITE_P( number: 0 options { features { - [pb.test] { int_enum_entry_feature: 1 } + [pb.test] { enum_entry_feature: VALUE1 } } } } @@ -10502,7 +10529,7 @@ INSTANTIATE_TEST_SUITE_P( name: "FooService" options { features { - [pb.test] { int_service_feature: 11 } + [pb.test] { service_feature: VALUE11 } } } } @@ -10522,7 +10549,7 @@ INSTANTIATE_TEST_SUITE_P( output_type: ".EmptyMessage" options { features { - [pb.test] { int_method_feature: 12 } + [pb.test] { method_feature: VALUE12 } } } } diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc index 3c179897b5..5780fcb208 100644 --- a/src/google/protobuf/duration.pb.cc +++ b/src/google/protobuf/duration.pb.cc @@ -6,6 +6,7 @@ #include "google/protobuf/duration.pb.h" #include +#include #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" @@ -145,6 +146,7 @@ Duration::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Duration, _impl_._cached_size_), false, @@ -319,8 +321,8 @@ namespace protobuf { } // namespace protobuf } // namespace google // @@protoc_insertion_point(global_scope) -PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 -static ::std::false_type _static_init_ PROTOBUF_UNUSED = - (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fduration_2eproto), - ::std::false_type{}); +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ PROTOBUF_UNUSED = + (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fduration_2eproto), + ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/editions/BUILD b/src/google/protobuf/editions/BUILD index f7fc387ad3..403eee868e 100644 --- a/src/google/protobuf/editions/BUILD +++ b/src/google/protobuf/editions/BUILD @@ -132,6 +132,13 @@ java_proto_library( deps = [":test_messages_proto2_editions_proto"], ) +java_lite_proto_library( + name = "test_messages_proto2_editions_java_proto_lite", + testonly = True, + visibility = ["//conformance:__pkg__"], + deps = [":test_messages_proto2_editions_proto"], +) + py_proto_library( name = "test_messages_proto2_editions_py_pb2", testonly = True, @@ -193,6 +200,13 @@ java_proto_library( deps = [":test_messages_proto3_editions_proto"], ) +java_lite_proto_library( + name = "test_messages_proto3_editions_java_proto_lite", + testonly = True, + visibility = ["//conformance:__pkg__"], + deps = [":test_messages_proto3_editions_proto"], +) + py_proto_library( name = "test_messages_proto3_editions_py_pb2", testonly = True, @@ -221,6 +235,7 @@ exports_files( ], visibility = [ "//python:__pkg__", + "//ruby:__pkg__", ], ) diff --git a/src/google/protobuf/editions/codegen_tests/proto3_packed.proto b/src/google/protobuf/editions/codegen_tests/proto3_packed.proto index ed7e38f404..3f511b540f 100644 --- a/src/google/protobuf/editions/codegen_tests/proto3_packed.proto +++ b/src/google/protobuf/editions/codegen_tests/proto3_packed.proto @@ -16,4 +16,5 @@ message Proto3Packed { int32 int32_field = 1; } repeated SubMessage sub_message_field = 3; + repeated int32 explicitly_packed = 4 [packed = true]; } diff --git a/src/google/protobuf/editions/defaults_test.cc b/src/google/protobuf/editions/defaults_test.cc index b699e5bbf9..c79988ae9f 100644 --- a/src/google/protobuf/editions/defaults_test.cc +++ b/src/google/protobuf/editions/defaults_test.cc @@ -52,11 +52,9 @@ TEST(DefaultsTest, Check2023) { EXPECT_EQ(defaults->defaults()[2].edition(), EDITION_2023); EXPECT_EQ(defaults->defaults()[2].features().field_presence(), FeatureSet::EXPLICIT); - EXPECT_EQ(defaults->defaults()[2] - .features() - .GetExtension(pb::test) - .int_file_feature(), - 1); + EXPECT_EQ( + defaults->defaults()[2].features().GetExtension(pb::test).file_feature(), + pb::VALUE3); } TEST(DefaultsTest, CheckFuture) { @@ -71,19 +69,15 @@ TEST(DefaultsTest, CheckFuture) { EXPECT_EQ(defaults->defaults()[2].edition(), EDITION_2023); EXPECT_EQ(defaults->defaults()[2].features().field_presence(), FeatureSet::EXPLICIT); - EXPECT_EQ(defaults->defaults()[2] - .features() - .GetExtension(pb::test) - .int_file_feature(), - 1); + EXPECT_EQ( + defaults->defaults()[2].features().GetExtension(pb::test).file_feature(), + pb::VALUE3); EXPECT_EQ(defaults->defaults()[3].edition(), EDITION_99997_TEST_ONLY); EXPECT_EQ(defaults->defaults()[3].features().field_presence(), FeatureSet::EXPLICIT); - EXPECT_EQ(defaults->defaults()[3] - .features() - .GetExtension(pb::test) - .int_file_feature(), - 2); + EXPECT_EQ( + defaults->defaults()[3].features().GetExtension(pb::test).file_feature(), + pb::VALUE4); } TEST(DefaultsTest, CheckFarFuture) { @@ -98,27 +92,21 @@ TEST(DefaultsTest, CheckFarFuture) { EXPECT_EQ(defaults->defaults()[2].edition(), EDITION_2023); EXPECT_EQ(defaults->defaults()[2].features().field_presence(), FeatureSet::EXPLICIT); - EXPECT_EQ(defaults->defaults()[2] - .features() - .GetExtension(pb::test) - .int_file_feature(), - 1); + EXPECT_EQ( + defaults->defaults()[2].features().GetExtension(pb::test).file_feature(), + pb::VALUE3); EXPECT_EQ(defaults->defaults()[3].edition(), EDITION_99997_TEST_ONLY); EXPECT_EQ(defaults->defaults()[3].features().field_presence(), FeatureSet::EXPLICIT); - EXPECT_EQ(defaults->defaults()[3] - .features() - .GetExtension(pb::test) - .int_file_feature(), - 2); + EXPECT_EQ( + defaults->defaults()[3].features().GetExtension(pb::test).file_feature(), + pb::VALUE4); EXPECT_EQ(defaults->defaults()[4].edition(), EDITION_99998_TEST_ONLY); EXPECT_EQ(defaults->defaults()[4].features().field_presence(), FeatureSet::EXPLICIT); - EXPECT_EQ(defaults->defaults()[4] - .features() - .GetExtension(pb::test) - .int_file_feature(), - 3); + EXPECT_EQ( + defaults->defaults()[4].features().GetExtension(pb::test).file_feature(), + pb::VALUE5); } TEST(DefaultsTest, Embedded) { @@ -135,11 +123,9 @@ TEST(DefaultsTest, Embedded) { EXPECT_EQ(defaults.defaults()[2].edition(), EDITION_2023); EXPECT_EQ(defaults.defaults()[2].features().field_presence(), FeatureSet::EXPLICIT); - EXPECT_EQ(defaults.defaults()[2] - .features() - .GetExtension(pb::test) - .int_file_feature(), - 1); + EXPECT_EQ( + defaults.defaults()[2].features().GetExtension(pb::test).file_feature(), + pb::VALUE3); } TEST(DefaultsTest, EmbeddedBase64) { @@ -159,11 +145,9 @@ TEST(DefaultsTest, EmbeddedBase64) { EXPECT_EQ(defaults.defaults()[2].edition(), EDITION_2023); EXPECT_EQ(defaults.defaults()[2].features().field_presence(), FeatureSet::EXPLICIT); - EXPECT_EQ(defaults.defaults()[2] - .features() - .GetExtension(pb::test) - .int_file_feature(), - 1); + EXPECT_EQ( + defaults.defaults()[2].features().GetExtension(pb::test).file_feature(), + pb::VALUE3); } } // namespace diff --git a/src/google/protobuf/editions/golden/compare_cpp_codegen_failure.xml b/src/google/protobuf/editions/golden/compare_cpp_codegen_failure.xml index 58c8c4e498..da5fb3d28a 100644 --- a/src/google/protobuf/editions/golden/compare_cpp_codegen_failure.xml +++ b/src/google/protobuf/editions/golden/compare_cpp_codegen_failure.xml @@ -2,7 +2,7 @@ - + diff --git a/src/google/protobuf/editions/golden/editions_transform_proto2.proto b/src/google/protobuf/editions/golden/editions_transform_proto2.proto index c8e9fb2b3e..0e538701b0 100644 --- a/src/google/protobuf/editions/golden/editions_transform_proto2.proto +++ b/src/google/protobuf/editions/golden/editions_transform_proto2.proto @@ -14,6 +14,7 @@ edition = "2023"; package protobuf_editions_test; +import "net/proto/proto1_features.proto"; import "third_party/java_src/protobuf/current/java/com/google/protobuf/java_features.proto"; import "google/protobuf/cpp_features.proto"; import "google/protobuf/editions/proto/editions_transform_proto3.proto"; @@ -21,7 +22,6 @@ import "google/protobuf/editions/proto/editions_transform_proto3.proto"; option features.repeated_field_encoding = EXPANDED; option features.utf8_validation = NONE; option java_multiple_files = true; -option cc_enable_arenas = true; message EmptyMessage { } @@ -79,7 +79,8 @@ message TestMessage { map string_map_field = 7; repeated int32 int_field = 8; repeated int32 int_field_packed = 9 [ - features.repeated_field_encoding = PACKED + features.repeated_field_encoding = PACKED, + features.(pb.proto1).legacy_packed = true ]; repeated int32 int_field_unpacked = 10; diff --git a/src/google/protobuf/editions/golden/editions_transform_proto3.proto b/src/google/protobuf/editions/golden/editions_transform_proto3.proto index 80123f4e50..cbb91d0fc0 100644 --- a/src/google/protobuf/editions/golden/editions_transform_proto3.proto +++ b/src/google/protobuf/editions/golden/editions_transform_proto3.proto @@ -9,6 +9,8 @@ edition = "2023"; package protobuf_editions_test; +import "net/proto/proto1_features.proto"; + option features.field_presence = IMPLICIT; enum TestEnumProto3 { @@ -20,7 +22,10 @@ message TestMessageProto3 { string string_field = 1; map string_map_field = 4; repeated int32 int_field = 7; - repeated int32 int_field_packed = 8; + repeated int32 int_field_packed = 8 [ + features.(pb.proto1).legacy_packed = true + ]; + repeated int32 int_field_unpacked = 9 [ features.repeated_field_encoding = EXPANDED ]; diff --git a/src/google/protobuf/editions/golden/test_messages_proto2_editions.proto b/src/google/protobuf/editions/golden/test_messages_proto2_editions.proto index 9f4f198318..ba9bbf6008 100644 --- a/src/google/protobuf/editions/golden/test_messages_proto2_editions.proto +++ b/src/google/protobuf/editions/golden/test_messages_proto2_editions.proto @@ -23,7 +23,6 @@ option objc_class_prefix = "EditionsProto2"; // This is the default, but we specify it here explicitly. option optimize_for = SPEED; -option cc_enable_arenas = true; // This proto includes every type of field in both singular and repeated // forms. diff --git a/src/google/protobuf/editions/golden/test_messages_proto3_editions.proto b/src/google/protobuf/editions/golden/test_messages_proto3_editions.proto index c092ea6c8d..0c0beceb22 100644 --- a/src/google/protobuf/editions/golden/test_messages_proto3_editions.proto +++ b/src/google/protobuf/editions/golden/test_messages_proto3_editions.proto @@ -28,7 +28,6 @@ option objc_class_prefix = "EditionsProto3"; // This is the default, but we specify it here explicitly. option optimize_for = SPEED; -option cc_enable_arenas = true; // This proto includes every type of field in both singular and repeated // forms. diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc index 16efefdd0d..a736987d9d 100644 --- a/src/google/protobuf/empty.pb.cc +++ b/src/google/protobuf/empty.pb.cc @@ -6,6 +6,7 @@ #include "google/protobuf/empty.pb.h" #include +#include #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" @@ -116,6 +117,7 @@ Empty::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Empty, _impl_._cached_size_), false, @@ -174,8 +176,8 @@ namespace protobuf { } // namespace protobuf } // namespace google // @@protoc_insertion_point(global_scope) -PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 -static ::std::false_type _static_init_ PROTOBUF_UNUSED = - (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fempty_2eproto), - ::std::false_type{}); +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ PROTOBUF_UNUSED = + (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fempty_2eproto), + ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc index 5c20f8190b..d4925174f8 100644 --- a/src/google/protobuf/extension_set.cc +++ b/src/google/protobuf/extension_set.cc @@ -154,7 +154,7 @@ void ExtensionSet::RegisterMessageExtension(const MessageLite* extendee, type == WireFormatLite::TYPE_GROUP); ExtensionInfo info(extendee, number, type, is_repeated, is_packed, verify_func, is_lazy); - info.message_info = {prototype}; + info.message_info = {prototype, prototype->GetTcParseTable()}; Register(info); } diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h index d9f25d5e2a..f2126bb8de 100644 --- a/src/google/protobuf/extension_set.h +++ b/src/google/protobuf/extension_set.h @@ -60,6 +60,7 @@ class Reflection; // message.h class UnknownFieldSet; // unknown_field_set.h class FeatureSet; namespace internal { +struct DescriptorTable; class FieldSkipper; // wire_format_lite.h class ReflectionVisit; // message_reflection_util.h class WireFormat; @@ -138,6 +139,8 @@ struct ExtensionInfo { struct MessageInfo { const MessageLite* prototype; + // The TcParse table used for this object. Never null. + const internal::TcParseTableBase* tc_table; }; union { @@ -157,6 +160,14 @@ struct ExtensionInfo { }; +// Reference to a prototype via its DescriptorTable. +// This way we can generate them on the fly if they are missing when Weak +// Descriptor messages are enabled. +struct WeakPrototypeRef { + const internal::DescriptorTable* table; + int index; +}; + // An ExtensionFinder is an object which looks up extension definitions. It // must implement this method: // @@ -225,6 +236,17 @@ class PROTOBUF_EXPORT ExtensionSet { LazyEagerVerifyFnType verify_func, LazyAnnotation is_lazy); + // As RegisterMessageExtension, but for the weak descriptor message mode. + // It will perform the registration in two phases to guarantee we can parse + // descriptors properly. + static void RegisterWeakMessageExtension(internal::WeakPrototypeRef extendee, + int number, FieldType type, + bool is_repeated, + internal::WeakPrototypeRef prototype, + LazyEagerVerifyFnType verify_func, + LazyAnnotation is_lazy, + bool is_preregistration); + // ================================================================= // Add all fields which are currently present to the given vector. This diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc index ffbea9b16d..dad4937993 100644 --- a/src/google/protobuf/extension_set_heavy.cc +++ b/src/google/protobuf/extension_set_heavy.cc @@ -23,6 +23,8 @@ #include "google/protobuf/descriptor.pb.h" #include "google/protobuf/extension_set.h" #include "google/protobuf/extension_set_inl.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/message.h" #include "google/protobuf/message_lite.h" @@ -271,6 +273,8 @@ bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) { if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { output->message_info.prototype = factory_->GetPrototype(extension->message_type()); + output->message_info.tc_table = + output->message_info.prototype->GetTcParseTable(); ABSL_CHECK(output->message_info.prototype != nullptr) << "Extension factory's GetPrototype() returned nullptr; extension: " << extension->full_name(); @@ -421,6 +425,43 @@ uint8_t* ExtensionSet::SerializeMessageSetWithCachedSizesToArray( &stream); } +#if defined(PROTOBUF_DESCRIPTOR_WEAK_MESSAGES_ALLOWED) +// First, register all the extensions that have both messages linked in. +// This will include all messages used as extensions in .proto options. +// In the second phase, we generate the missing prototypes, but that requires +// parsing descriptors, which in turn require the extensions from the first +// phase. +void ExtensionSet::RegisterWeakMessageExtension( + internal::WeakPrototypeRef extendee, int number, FieldType type, + bool is_repeated, internal::WeakPrototypeRef prototype, + LazyEagerVerifyFnType verify_func, LazyAnnotation is_lazy, + bool is_preregistration) { + auto* extendee_msg = + GetPrototypeForWeakDescriptor(extendee.table, extendee.index, false); + auto* prototype_msg = + GetPrototypeForWeakDescriptor(prototype.table, prototype.index, false); + + const bool have_both = extendee_msg != nullptr && prototype_msg != nullptr; + if (is_preregistration != have_both) { + // This is done on the other phase. + return; + } + + if (extendee_msg == nullptr) { + extendee_msg = + GetPrototypeForWeakDescriptor(extendee.table, extendee.index, true); + } + if (prototype_msg == nullptr) { + prototype_msg = + GetPrototypeForWeakDescriptor(prototype.table, prototype.index, true); + } + + ExtensionSet::RegisterMessageExtension( + extendee_msg, number, type, is_repeated, + /*is_packed=*/false, prototype_msg, verify_func, is_lazy); +} +#endif // PROTOBUF_DESCRIPTOR_WEAK_MESSAGES_ALLOWED + } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/feature_resolver.cc b/src/google/protobuf/feature_resolver.cc index e799e12da1..a820b99021 100644 --- a/src/google/protobuf/feature_resolver.cc +++ b/src/google/protobuf/feature_resolver.cc @@ -69,6 +69,11 @@ absl::Status ValidateDescriptor(const Descriptor& descriptor) { return Error("Feature field ", field.full_name(), " is an unsupported repeated field."); } + if (field.type() != FieldDescriptor::TYPE_ENUM && + field.type() != FieldDescriptor::TYPE_BOOL) { + return Error("Feature field ", field.full_name(), + " is not an enum or boolean."); + } if (field.options().targets().empty()) { return Error("Feature field ", field.full_name(), " has no target specified."); diff --git a/src/google/protobuf/feature_resolver_test.cc b/src/google/protobuf/feature_resolver_test.cc index 2e2a6ebb49..a16ab656d3 100644 --- a/src/google/protobuf/feature_resolver_test.cc +++ b/src/google/protobuf/feature_resolver_test.cc @@ -19,6 +19,7 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/string_view.h" +#include "absl/strings/substitute.h" #include "google/protobuf/compiler/parser.h" #include "google/protobuf/cpp_features.pb.h" #include "google/protobuf/descriptor.h" @@ -127,21 +128,16 @@ TEST(FeatureResolverTest, DefaultsTest2023) { EXPECT_EQ(merged->message_encoding(), FeatureSet::LENGTH_PREFIXED); const pb::TestFeatures& ext = merged->GetExtension(pb::test); - EXPECT_EQ(ext.int_file_feature(), 1); - EXPECT_EQ(ext.int_extension_range_feature(), 1); - EXPECT_EQ(ext.int_message_feature(), 1); - EXPECT_EQ(ext.int_field_feature(), 1); - EXPECT_EQ(ext.int_oneof_feature(), 1); - EXPECT_EQ(ext.int_enum_feature(), 1); - EXPECT_EQ(ext.int_enum_entry_feature(), 1); - EXPECT_EQ(ext.int_service_feature(), 1); - EXPECT_EQ(ext.int_method_feature(), 1); - EXPECT_EQ(ext.bool_field_feature(), false); - EXPECT_FLOAT_EQ(ext.float_field_feature(), 1.1); - EXPECT_THAT(ext.message_field_feature(), - EqualsProto("bool_field: true int_field: 1 float_field: 1.5 " - "string_field: '2023'")); - EXPECT_EQ(ext.enum_field_feature(), pb::TestFeatures::ENUM_VALUE1); + EXPECT_EQ(ext.file_feature(), pb::VALUE3); + EXPECT_EQ(ext.extension_range_feature(), pb::VALUE1); + EXPECT_EQ(ext.message_feature(), pb::VALUE1); + EXPECT_EQ(ext.field_feature(), pb::VALUE1); + EXPECT_EQ(ext.oneof_feature(), pb::VALUE1); + EXPECT_EQ(ext.enum_feature(), pb::VALUE1); + EXPECT_EQ(ext.enum_entry_feature(), pb::VALUE1); + EXPECT_EQ(ext.service_feature(), pb::VALUE1); + EXPECT_EQ(ext.method_feature(), pb::VALUE1); + EXPECT_FALSE(ext.bool_field_feature()); } TEST(FeatureResolverTest, DefaultsTestMessageExtension) { @@ -157,21 +153,16 @@ TEST(FeatureResolverTest, DefaultsTestMessageExtension) { const pb::TestFeatures& ext = merged->GetExtension(pb::TestMessage::test_message); - EXPECT_EQ(ext.int_file_feature(), 1); - EXPECT_EQ(ext.int_extension_range_feature(), 1); - EXPECT_EQ(ext.int_message_feature(), 1); - EXPECT_EQ(ext.int_field_feature(), 1); - EXPECT_EQ(ext.int_oneof_feature(), 1); - EXPECT_EQ(ext.int_enum_feature(), 1); - EXPECT_EQ(ext.int_enum_entry_feature(), 1); - EXPECT_EQ(ext.int_service_feature(), 1); - EXPECT_EQ(ext.int_method_feature(), 1); - EXPECT_EQ(ext.bool_field_feature(), false); - EXPECT_FLOAT_EQ(ext.float_field_feature(), 1.1); - EXPECT_THAT(ext.message_field_feature(), - EqualsProto("bool_field: true int_field: 1 float_field: 1.5 " - "string_field: '2023'")); - EXPECT_EQ(ext.enum_field_feature(), pb::TestFeatures::ENUM_VALUE1); + EXPECT_EQ(ext.file_feature(), pb::VALUE3); + EXPECT_EQ(ext.extension_range_feature(), pb::VALUE1); + EXPECT_EQ(ext.message_feature(), pb::VALUE1); + EXPECT_EQ(ext.field_feature(), pb::VALUE1); + EXPECT_EQ(ext.oneof_feature(), pb::VALUE1); + EXPECT_EQ(ext.enum_feature(), pb::VALUE1); + EXPECT_EQ(ext.enum_entry_feature(), pb::VALUE1); + EXPECT_EQ(ext.service_feature(), pb::VALUE1); + EXPECT_EQ(ext.method_feature(), pb::VALUE1); + EXPECT_FALSE(ext.bool_field_feature()); } TEST(FeatureResolverTest, DefaultsTestNestedExtension) { @@ -187,21 +178,16 @@ TEST(FeatureResolverTest, DefaultsTestNestedExtension) { const pb::TestFeatures& ext = merged->GetExtension(pb::TestMessage::Nested::test_nested); - EXPECT_EQ(ext.int_file_feature(), 1); - EXPECT_EQ(ext.int_extension_range_feature(), 1); - EXPECT_EQ(ext.int_message_feature(), 1); - EXPECT_EQ(ext.int_field_feature(), 1); - EXPECT_EQ(ext.int_oneof_feature(), 1); - EXPECT_EQ(ext.int_enum_feature(), 1); - EXPECT_EQ(ext.int_enum_entry_feature(), 1); - EXPECT_EQ(ext.int_service_feature(), 1); - EXPECT_EQ(ext.int_method_feature(), 1); - EXPECT_EQ(ext.bool_field_feature(), false); - EXPECT_FLOAT_EQ(ext.float_field_feature(), 1.1); - EXPECT_THAT(ext.message_field_feature(), - EqualsProto("bool_field: true int_field: 1 float_field: 1.5 " - "string_field: '2023'")); - EXPECT_EQ(ext.enum_field_feature(), pb::TestFeatures::ENUM_VALUE1); + EXPECT_EQ(ext.file_feature(), pb::VALUE3); + EXPECT_EQ(ext.extension_range_feature(), pb::VALUE1); + EXPECT_EQ(ext.message_feature(), pb::VALUE1); + EXPECT_EQ(ext.field_feature(), pb::VALUE1); + EXPECT_EQ(ext.oneof_feature(), pb::VALUE1); + EXPECT_EQ(ext.enum_feature(), pb::VALUE1); + EXPECT_EQ(ext.enum_entry_feature(), pb::VALUE1); + EXPECT_EQ(ext.service_feature(), pb::VALUE1); + EXPECT_EQ(ext.method_feature(), pb::VALUE1); + EXPECT_FALSE(ext.bool_field_feature()); } TEST(FeatureResolverTest, DefaultsGeneratedPoolCustom) { @@ -222,7 +208,7 @@ TEST(FeatureResolverTest, DefaultsGeneratedPoolCustom) { EXPECT_EQ(merged.field_presence(), FeatureSet::EXPLICIT); EXPECT_TRUE(merged.HasExtension(pb::test)); - EXPECT_EQ(merged.GetExtension(pb::test).int_file_feature(), 1); + EXPECT_EQ(merged.GetExtension(pb::test).file_feature(), pb::VALUE3); EXPECT_FALSE(merged.HasExtension(pb::cpp)); } @@ -245,11 +231,8 @@ TEST(FeatureResolverTest, DefaultsFarFuture) { ASSERT_OK(merged); pb::TestFeatures ext = merged->GetExtension(pb::test); - EXPECT_EQ(ext.int_file_feature(), 3); - EXPECT_THAT(ext.message_field_feature(), - EqualsProto("bool_field: true int_field: 2 float_field: 1.5 " - "string_field: '2024'")); - EXPECT_EQ(ext.enum_field_feature(), pb::TestFeatures::ENUM_VALUE3); + EXPECT_EQ(ext.file_feature(), pb::VALUE5); + EXPECT_TRUE(ext.bool_field_feature()); } TEST(FeatureResolverTest, DefaultsMiddleEdition) { @@ -258,43 +241,8 @@ TEST(FeatureResolverTest, DefaultsMiddleEdition) { ASSERT_OK(merged); pb::TestFeatures ext = merged->GetExtension(pb::test); - EXPECT_EQ(ext.int_file_feature(), 2); - EXPECT_EQ(ext.enum_field_feature(), pb::TestFeatures::ENUM_VALUE2); -} - -TEST(FeatureResolverTest, DefaultsMessageMerge) { - { - absl::StatusOr merged = GetDefaults(EDITION_2023, pb::test); - ASSERT_OK(merged); - pb::TestFeatures ext = merged->GetExtension(pb::test); - EXPECT_THAT(ext.message_field_feature(), - EqualsProto(R"pb(bool_field: true - int_field: 1 - float_field: 1.5 - string_field: '2023')pb")); - } - { - absl::StatusOr merged = - GetDefaults(EDITION_99997_TEST_ONLY, pb::test); - ASSERT_OK(merged); - pb::TestFeatures ext = merged->GetExtension(pb::test); - EXPECT_THAT(ext.message_field_feature(), - EqualsProto(R"pb(bool_field: true - int_field: 2 - float_field: 1.5 - string_field: '2023')pb")); - } - { - absl::StatusOr merged = - GetDefaults(EDITION_99998_TEST_ONLY, pb::test); - ASSERT_OK(merged); - pb::TestFeatures ext = merged->GetExtension(pb::test); - EXPECT_THAT(ext.message_field_feature(), - EqualsProto(R"pb(bool_field: true - int_field: 2 - float_field: 1.5 - string_field: '2024')pb")); - } + EXPECT_EQ(ext.file_feature(), pb::VALUE4); + EXPECT_TRUE(ext.bool_field_feature()); } TEST(FeatureResolverTest, CreateFromUnsortedDefaults) { @@ -412,11 +360,7 @@ TEST(FeatureResolverTest, MergeFeaturesChildOverrideComplex) { FeatureSet child = ParseTextOrDie(R"pb( field_presence: IMPLICIT repeated_field_encoding: EXPANDED - [pb.test] { - int_field_feature: 5 - enum_field_feature: ENUM_VALUE4 - message_field_feature { int_field: 10 } - } + [pb.test] { field_feature: VALUE5 } )pb"); absl::StatusOr merged = resolver->MergeFeatures(FeatureSet(), child); @@ -428,13 +372,8 @@ TEST(FeatureResolverTest, MergeFeaturesChildOverrideComplex) { EXPECT_EQ(merged->message_encoding(), FeatureSet::LENGTH_PREFIXED); pb::TestFeatures ext = merged->GetExtension(pb::test); - EXPECT_EQ(ext.int_file_feature(), 1); - EXPECT_EQ(ext.int_field_feature(), 5); - EXPECT_FLOAT_EQ(ext.float_field_feature(), 1.1); - EXPECT_THAT(ext.message_field_feature(), - EqualsProto("bool_field: true int_field: 10 float_field: 1.5 " - "string_field: '2023'")); - EXPECT_EQ(ext.enum_field_feature(), pb::TestFeatures::ENUM_VALUE4); + EXPECT_EQ(ext.file_feature(), pb::VALUE3); + EXPECT_EQ(ext.field_feature(), pb::VALUE5); } TEST(FeatureResolverTest, MergeFeaturesParentOverrides) { @@ -444,18 +383,11 @@ TEST(FeatureResolverTest, MergeFeaturesParentOverrides) { FeatureSet parent = ParseTextOrDie(R"pb( field_presence: IMPLICIT repeated_field_encoding: EXPANDED - [pb.test] { - int_field_feature: 5 - enum_field_feature: ENUM_VALUE4 - message_field_feature { int_field: 10 string_field: "parent" } - } + [pb.test] { message_feature: VALUE2 field_feature: VALUE5 } )pb"); FeatureSet child = ParseTextOrDie(R"pb( repeated_field_encoding: PACKED - [pb.test] { - int_field_feature: 9 - message_field_feature { bool_field: false int_field: 9 } - } + [pb.test] { field_feature: VALUE7 } )pb"); absl::StatusOr merged = resolver->MergeFeatures(parent, child); ASSERT_OK(merged); @@ -466,21 +398,16 @@ TEST(FeatureResolverTest, MergeFeaturesParentOverrides) { EXPECT_EQ(merged->message_encoding(), FeatureSet::LENGTH_PREFIXED); pb::TestFeatures ext = merged->GetExtension(pb::test); - EXPECT_EQ(ext.int_file_feature(), 1); - EXPECT_EQ(ext.int_extension_range_feature(), 1); - EXPECT_EQ(ext.int_message_feature(), 1); - EXPECT_EQ(ext.int_field_feature(), 9); - EXPECT_EQ(ext.int_oneof_feature(), 1); - EXPECT_EQ(ext.int_enum_feature(), 1); - EXPECT_EQ(ext.int_enum_entry_feature(), 1); - EXPECT_EQ(ext.int_service_feature(), 1); - EXPECT_EQ(ext.int_method_feature(), 1); - EXPECT_EQ(ext.bool_field_feature(), false); - EXPECT_FLOAT_EQ(ext.float_field_feature(), 1.1); - EXPECT_THAT(ext.message_field_feature(), - EqualsProto("bool_field: false int_field: 9 float_field: 1.5 " - "string_field: 'parent'")); - EXPECT_EQ(ext.enum_field_feature(), pb::TestFeatures::ENUM_VALUE4); + EXPECT_EQ(ext.file_feature(), pb::VALUE3); + EXPECT_EQ(ext.extension_range_feature(), pb::VALUE1); + EXPECT_EQ(ext.message_feature(), pb::VALUE2); + EXPECT_EQ(ext.field_feature(), pb::VALUE7); + EXPECT_EQ(ext.oneof_feature(), pb::VALUE1); + EXPECT_EQ(ext.enum_feature(), pb::VALUE1); + EXPECT_EQ(ext.enum_entry_feature(), pb::VALUE1); + EXPECT_EQ(ext.service_feature(), pb::VALUE1); + EXPECT_EQ(ext.method_feature(), pb::VALUE1); + EXPECT_FALSE(ext.bool_field_feature()); } TEST(FeatureResolverTest, MergeFeaturesUnknownEnumFeature) { @@ -510,13 +437,13 @@ TEST(FeatureResolverTest, MergeFeaturesExtensionEnumUnknown) { SetupFeatureResolver(EDITION_2023, pb::test); ASSERT_OK(resolver); FeatureSet child = ParseTextOrDie(R"pb( - [pb.test] { enum_field_feature: TEST_ENUM_FEATURE_UNKNOWN } + [pb.test] { field_feature: TEST_ENUM_FEATURE_UNKNOWN } )pb"); absl::StatusOr merged = resolver->MergeFeatures(FeatureSet(), child); ASSERT_OK(merged); - EXPECT_EQ(merged->GetExtension(pb::test).enum_field_feature(), - pb::TestFeatures::TEST_ENUM_FEATURE_UNKNOWN); + EXPECT_EQ(merged->GetExtension(pb::test).field_feature(), + pb::TEST_ENUM_FEATURE_UNKNOWN); } TEST(FeatureResolverTest, MergeFeaturesDistantPast) { @@ -737,8 +664,8 @@ TEST_F(FeatureResolverPoolTest, CompileDefaultsInvalidWithMissingTarget) { optional Foo bar = 9999; } message Foo { - optional int32 int_field = 1 [ - edition_defaults = { edition: EDITION_2023, value: "1" } + optional bool bool_field = 1 [ + edition_defaults = { edition: EDITION_2023, value: "true" } ]; } )schema"); @@ -747,107 +674,10 @@ TEST_F(FeatureResolverPoolTest, CompileDefaultsInvalidWithMissingTarget) { const FieldDescriptor* ext = file->extension(0); EXPECT_THAT(FeatureResolver::CompileDefaults(feature_set_, {ext}, EDITION_2023, EDITION_2023), - HasError(AllOf(HasSubstr("test.Foo.int_field"), + HasError(AllOf(HasSubstr("test.Foo.bool_field"), HasSubstr("no target specified")))); } -TEST_F(FeatureResolverPoolTest, - CompileDefaultsInvalidDefaultsMessageParsingError) { - const FileDescriptor* file = ParseSchema(R"schema( - syntax = "proto2"; - package test; - import "google/protobuf/descriptor.proto"; - - extend google.protobuf.FeatureSet { - optional Foo bar = 9999; - } - message Foo { - message MessageFeature { - optional int32 int_field = 1; - } - optional MessageFeature message_field_feature = 12 [ - targets = TARGET_TYPE_FIELD, - edition_defaults = { edition: EDITION_PROTO2, value: "9987" } - ]; - } - )schema"); - ASSERT_NE(file, nullptr); - - const FieldDescriptor* ext = file->extension(0); - EXPECT_THAT( - FeatureResolver::CompileDefaults(feature_set_, {ext}, EDITION_2023, - EDITION_2023), - HasError(AllOf(HasSubstr("in edition_defaults"), HasSubstr("9987")))); -} - -TEST_F(FeatureResolverPoolTest, - CompileDefaultsInvalidDefaultsMessageParsingErrorMerged) { - const FileDescriptor* file = ParseSchema(R"schema( - syntax = "proto2"; - package test; - import "google/protobuf/descriptor.proto"; - - extend google.protobuf.FeatureSet { - optional Foo bar = 9999; - } - message Foo { - message MessageFeature { - optional int32 int_field = 1; - } - optional MessageFeature message_field_feature = 12 [ - targets = TARGET_TYPE_FIELD, - edition_defaults = { edition: EDITION_99998_TEST_ONLY, value: "int_field: 2" }, - edition_defaults = { edition: EDITION_99997_TEST_ONLY, value: "int_field: 1" }, - edition_defaults = { edition: EDITION_PROTO2, value: "" }, - edition_defaults = { edition: EDITION_2023, value: "9987" } - ]; - } - )schema"); - ASSERT_NE(file, nullptr); - - const FieldDescriptor* ext = file->extension(0); - EXPECT_THAT( - FeatureResolver::CompileDefaults(feature_set_, {ext}, EDITION_2023, - EDITION_99998_TEST_ONLY), - HasError(AllOf(HasSubstr("in edition_defaults"), HasSubstr("9987")))); -} - -TEST_F(FeatureResolverPoolTest, - CompileDefaultsInvalidDefaultsMessageParsingErrorSkipped) { - const FileDescriptor* file = ParseSchema(R"schema( - syntax = "proto2"; - package test; - import "google/protobuf/descriptor.proto"; - - extend google.protobuf.FeatureSet { - optional Foo bar = 9999; - } - message Foo { - message MessageFeature { - optional int32 int_field = 1; - } - optional MessageFeature message_field_feature = 12 [ - targets = TARGET_TYPE_FIELD, - edition_defaults = { edition: EDITION_99997_TEST_ONLY, value: "int_field: 2" }, - edition_defaults = { edition: EDITION_2023, value: "int_field: 1" }, - edition_defaults = { edition: EDITION_99998_TEST_ONLY, value: "9987" }, - edition_defaults = { edition: EDITION_PROTO2, value: "" } - ]; - } - )schema"); - ASSERT_NE(file, nullptr); - - const FieldDescriptor* ext = file->extension(0); - auto defaults = FeatureResolver::CompileDefaults( - feature_set_, {ext}, EDITION_2023, EDITION_99997_TEST_ONLY); - ASSERT_OK(defaults); - - auto resolver = FeatureResolver::Create(EDITION_2023, *defaults); - ASSERT_OK(resolver); - FeatureSet parent, child; - EXPECT_OK(resolver->MergeFeatures(parent, child)); -} - TEST_F(FeatureResolverPoolTest, CompileDefaultsInvalidDefaultsScalarParsingError) { const FileDescriptor* file = ParseSchema(R"schema( @@ -859,7 +689,7 @@ TEST_F(FeatureResolverPoolTest, optional Foo bar = 9999; } message Foo { - optional int32 int_field_feature = 12 [ + optional bool field_feature = 12 [ targets = TARGET_TYPE_FIELD, edition_defaults = { edition: EDITION_PROTO2, value: "1.23" } ]; @@ -885,10 +715,10 @@ TEST_F(FeatureResolverPoolTest, optional Foo bar = 9999; } message Foo { - optional int32 int_field_feature = 12 [ + optional bool field_feature = 12 [ targets = TARGET_TYPE_FIELD, edition_defaults = { edition: EDITION_99997_TEST_ONLY, value: "1.5" }, - edition_defaults = { edition: EDITION_PROTO2, value: "1" } + edition_defaults = { edition: EDITION_PROTO2, value: "true" } ]; } )schema"); @@ -915,9 +745,9 @@ TEST_F(FeatureResolverPoolTest, CompileDefaultsInvalidDefaultsTooEarly) { optional Foo bar = 9999; } message Foo { - optional int32 int_field_feature = 12 [ + optional bool field_feature = 12 [ targets = TARGET_TYPE_FIELD, - edition_defaults = { edition: EDITION_2_TEST_ONLY, value: "1" } + edition_defaults = { edition: EDITION_2_TEST_ONLY, value: "true" } ]; } )schema"); @@ -940,9 +770,9 @@ TEST_F(FeatureResolverPoolTest, CompileDefaultsMinimumTooEarly) { optional Foo bar = 9999; } message Foo { - optional int32 int_field_feature = 12 [ + optional bool field_feature = 12 [ targets = TARGET_TYPE_FIELD, - edition_defaults = { edition: EDITION_PROTO2, value: "1" } + edition_defaults = { edition: EDITION_PROTO2, value: "true" } ]; } )schema"); @@ -964,12 +794,18 @@ TEST_F(FeatureResolverPoolTest, CompileDefaultsMinimumCovered) { extend google.protobuf.FeatureSet { optional Foo bar = 9999; } + enum Bar { + TEST_ENUM_FEATURE_UNKNOWN = 0; + VALUE1 = 1; + VALUE2 = 2; + VALUE3 = 3; + } message Foo { - optional int32 int_file_feature = 1 [ + optional Bar file_feature = 1 [ targets = TARGET_TYPE_FIELD, - edition_defaults = { edition: EDITION_99998_TEST_ONLY, value: "2" }, - edition_defaults = { edition: EDITION_2023, value: "1" }, - edition_defaults = { edition: EDITION_PROTO2, value: "0" } + edition_defaults = { edition: EDITION_99998_TEST_ONLY, value: "VALUE3" }, + edition_defaults = { edition: EDITION_2023, value: "VALUE2" }, + edition_defaults = { edition: EDITION_PROTO2, value: "VALUE1" } ]; } )schema"); @@ -992,7 +828,7 @@ TEST_F(FeatureResolverPoolTest, CompileDefaultsMinimumCovered) { utf8_validation: NONE message_encoding: LENGTH_PREFIXED json_format: LEGACY_BEST_EFFORT - [pb.test] { int_file_feature: 0 } + [pb.test] { file_feature: VALUE1 } } } defaults { @@ -1004,7 +840,7 @@ TEST_F(FeatureResolverPoolTest, CompileDefaultsMinimumCovered) { utf8_validation: VERIFY message_encoding: LENGTH_PREFIXED json_format: ALLOW - [pb.test] { int_file_feature: 0 } + [pb.test] { file_feature: VALUE1 } } } defaults { @@ -1016,7 +852,7 @@ TEST_F(FeatureResolverPoolTest, CompileDefaultsMinimumCovered) { utf8_validation: VERIFY message_encoding: LENGTH_PREFIXED json_format: ALLOW - [pb.test] { int_file_feature: 1 } + [pb.test] { file_feature: VALUE2 } } } defaults { @@ -1028,12 +864,50 @@ TEST_F(FeatureResolverPoolTest, CompileDefaultsMinimumCovered) { utf8_validation: VERIFY message_encoding: LENGTH_PREFIXED json_format: ALLOW - [pb.test] { int_file_feature: 2 } + [pb.test] { file_feature: VALUE3 } } } )pb")); } +class FeatureUnboundedTypeTest + : public FeatureResolverPoolTest, + public ::testing::WithParamInterface {}; + +TEST_P(FeatureUnboundedTypeTest, CompileDefaults) { + const FileDescriptor* file = ParseSchema(absl::Substitute(R"schema( + syntax = "proto2"; + package test; + import "google/protobuf/descriptor.proto"; + + extend google.protobuf.FeatureSet { + optional Foo bar = 9999; + } + message SomeMessage { + optional bool value = 1; + } + message Foo { + optional $0 field_feature = 12 [ + targets = TARGET_TYPE_FIELD, + edition_defaults = { edition: EDITION_PROTO2, value: "1" } + ]; + } + )schema", + GetParam())); + ASSERT_NE(file, nullptr); + + const FieldDescriptor* ext = file->extension(0); + EXPECT_THAT( + FeatureResolver::CompileDefaults(feature_set_, {ext}, EDITION_1_TEST_ONLY, + EDITION_99997_TEST_ONLY), + HasError(HasSubstr("is not an enum or boolean"))); +} + +INSTANTIATE_TEST_SUITE_P(FeatureUnboundedTypeTestImpl, FeatureUnboundedTypeTest, + testing::Values("int32", "int64", "uint32", "string", + "bytes", "float", "double", + "SomeMessage")); + } // namespace } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc index ccc47a92d4..39840ba0c0 100644 --- a/src/google/protobuf/field_mask.pb.cc +++ b/src/google/protobuf/field_mask.pb.cc @@ -6,6 +6,7 @@ #include "google/protobuf/field_mask.pb.h" #include +#include #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" @@ -151,6 +152,7 @@ FieldMask::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(FieldMask, _impl_._cached_size_), false, @@ -298,8 +300,8 @@ namespace protobuf { } // namespace protobuf } // namespace google // @@protoc_insertion_point(global_scope) -PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 -static ::std::false_type _static_init_ PROTOBUF_UNUSED = - (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto), - ::std::false_type{}); +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ PROTOBUF_UNUSED = + (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto), + ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index 436856f57c..5334e401dc 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -1168,6 +1168,14 @@ void Reflection::SwapFieldsImpl( } } +template void Reflection::SwapFieldsImpl( + Message* message1, Message* message2, + const std::vector& fields) const; + +template void Reflection::SwapFieldsImpl( + Message* message1, Message* message2, + const std::vector& fields) const; + void Reflection::SwapFields( Message* message1, Message* message2, const std::vector& fields) const { @@ -2223,8 +2231,7 @@ void Reflection::AddEnumValueInternal(Message* message, int value) const { if (field->is_extension()) { MutableExtensionSet(message)->AddEnum(field->number(), field->type(), - field->options().packed(), value, - field); + field->is_packed(), value, field); } else { AddField(message, field, value); } @@ -3771,8 +3778,9 @@ bool SplitFieldHasExtraIndirection(const FieldDescriptor* field) { return field->is_repeated(); } +#if defined(PROTOBUF_DESCRIPTOR_WEAK_MESSAGES_ALLOWED) const Message* GetPrototypeForWeakDescriptor(const DescriptorTable* table, - int index) { + int index, bool force_build) { // First, make sure we inject the surviving default instances. InitProtobufDefaults(); @@ -3781,6 +3789,10 @@ const Message* GetPrototypeForWeakDescriptor(const DescriptorTable* table, return msg; } + if (!force_build) { + return nullptr; + } + // Fallback to dynamic messages. // Register the dep and generate the prototype via the generated pool. AssignDescriptors(table); @@ -3798,6 +3810,7 @@ const Message* GetPrototypeForWeakDescriptor(const DescriptorTable* table, return MessageFactory::generated_factory()->GetPrototype(descriptor); } +#endif // PROTOBUF_DESCRIPTOR_WEAK_MESSAGES_ALLOWED } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h index b888661b40..aa75cd0a95 100644 --- a/src/google/protobuf/generated_message_reflection.h +++ b/src/google/protobuf/generated_message_reflection.h @@ -339,9 +339,11 @@ struct PROTOBUF_EXPORT AddDescriptorsRunner { }; // Retrieves the existing prototype out of a descriptor table. -// If it doesn't exist, asks the generated message factory for one. +// If it doesn't exist: +// - If force_build is true, asks the generated message factory for one. +// - Otherwise, return null const Message* GetPrototypeForWeakDescriptor(const DescriptorTable* table, - int index); + int index, bool force_build); struct DenseEnumCacheInfo { std::atomic cache; diff --git a/src/google/protobuf/generated_message_tctable_impl.h b/src/google/protobuf/generated_message_tctable_impl.h index 260556d7f9..838e748501 100644 --- a/src/google/protobuf/generated_message_tctable_impl.h +++ b/src/google/protobuf/generated_message_tctable_impl.h @@ -14,6 +14,7 @@ #include #include +#include "absl/base/optimization.h" #include "absl/log/absl_log.h" #include "google/protobuf/extension_set.h" #include "google/protobuf/generated_message_tctable_decl.h" @@ -377,6 +378,22 @@ class PROTOBUF_EXPORT TcParser final { return &T::_table_.header; } + static PROTOBUF_ALWAYS_INLINE const char* ParseMessage( + MessageLite* msg, const char* ptr, ParseContext* ctx, + const TcParseTableBase* tc_table) { + return ctx->ParseLengthDelimitedInlined(ptr, [&](const char* ptr) { + return ParseLoopInlined(msg, ptr, ctx, tc_table); + }); + } + + static PROTOBUF_ALWAYS_INLINE const char* ParseGroup( + MessageLite* msg, const char* ptr, ParseContext* ctx, + const TcParseTableBase* tc_table, uint32_t start_tag) { + return ctx->ParseGroupInlined(ptr, start_tag, [&](const char* ptr) { + return ParseLoopInlined(msg, ptr, ctx, tc_table); + }); + } + // == ABI of the tail call functions == // All the tail call functions have the same signature as required by clang's // `musttail` attribute. However, their ABIs are different. @@ -976,6 +993,35 @@ inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ToParseLoop( return ptr; } +inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ParseLoopInlined( + MessageLite* msg, const char* ptr, ParseContext* ctx, + const TcParseTableBase* table) { + // Note: TagDispatch uses a dispatch table at "&table->fast_entries". + // For fast dispatch, we'd like to have a pointer to that, but if we use + // that expression, there's no easy way to get back to "table", which we also + // need during dispatch. It turns out that "table + 1" points exactly to + // fast_entries, so we just increment table by 1 here, to get the register + // holding the value we want. + table += 1; + while (!ctx->Done(&ptr)) { +#if defined(__GNUC__) + // Note: this asm prevents the compiler (clang, specifically) from + // believing (thanks to CSE) that it needs to dedicate a registeer both + // to "table" and "&table->fast_entries". + // TODO: remove this asm + asm("" : "+r"(table)); +#endif + ptr = TagDispatch(msg, ptr, ctx, TcFieldData::DefaultInit(), table - 1, 0); + if (ptr == nullptr) break; + if (ctx->LastTag() != 1) break; // Ended on terminating tag + } + table -= 1; + if (ABSL_PREDICT_FALSE(table->has_post_loop_handler)) { + return table->post_loop_handler(msg, ptr, ctx); + } + return ptr; +} + // Prints the type card as or of labels, using known higher level labels. // Used for code generation, but also useful for debugging. PROTOBUF_EXPORT std::string TypeCardToString(uint16_t type_card); diff --git a/src/google/protobuf/generated_message_tctable_lite.cc b/src/google/protobuf/generated_message_tctable_lite.cc index 9d1ec992fe..f8b0d87942 100644 --- a/src/google/protobuf/generated_message_tctable_lite.cc +++ b/src/google/protobuf/generated_message_tctable_lite.cc @@ -73,35 +73,6 @@ const char* TcParser::GenericFallbackLite(PROTOBUF_TC_PARAM_DECL) { // Core fast parsing implementation: ////////////////////////////////////////////////////////////////////////////// -inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ParseLoopInlined( - MessageLite* msg, const char* ptr, ParseContext* ctx, - const TcParseTableBase* table) { - // Note: TagDispatch uses a dispatch table at "&table->fast_entries". - // For fast dispatch, we'd like to have a pointer to that, but if we use - // that expression, there's no easy way to get back to "table", which we also - // need during dispatch. It turns out that "table + 1" points exactly to - // fast_entries, so we just increment table by 1 here, to get the register - // holding the value we want. - table += 1; - while (!ctx->Done(&ptr)) { -#if defined(__GNUC__) - // Note: this asm prevents the compiler (clang, specifically) from - // believing (thanks to CSE) that it needs to dedicate a registeer both - // to "table" and "&table->fast_entries". - // TODO: remove this asm - asm("" : "+r"(table)); -#endif - ptr = TagDispatch(msg, ptr, ctx, TcFieldData::DefaultInit(), table - 1, 0); - if (ptr == nullptr) break; - if (ctx->LastTag() != 1) break; // Ended on terminating tag - } - table -= 1; - if (ABSL_PREDICT_FALSE(table->has_post_loop_handler)) { - return table->post_loop_handler(msg, ptr, ctx); - } - return ptr; -} - PROTOBUF_NOINLINE const char* TcParser::ParseLoop( MessageLite* msg, const char* ptr, ParseContext* ctx, const TcParseTableBase* table) { diff --git a/src/google/protobuf/io/io_win32.cc b/src/google/protobuf/io/io_win32.cc index ea43104b95..f39d356ab2 100644 --- a/src/google/protobuf/io/io_win32.cc +++ b/src/google/protobuf/io/io_win32.cc @@ -28,14 +28,12 @@ #include "google/protobuf/io/io_win32.h" -#include #include #include #include #include #include #include -#include #include "absl/strings/ascii.h" @@ -71,7 +69,9 @@ struct CharTraits { template <> struct CharTraits { - static bool is_alpha(wchar_t ch) { return iswalpha(ch); } + static bool is_alpha(wchar_t ch) { + return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); + } }; template diff --git a/src/google/protobuf/map_lite_unittest.proto b/src/google/protobuf/map_lite_unittest.proto index b7ff3c5084..b42b3de88e 100644 --- a/src/google/protobuf/map_lite_unittest.proto +++ b/src/google/protobuf/map_lite_unittest.proto @@ -5,12 +5,14 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto2"; +edition = "2023"; package protobuf_unittest; import "google/protobuf/unittest_lite.proto"; +option features.enum_type = CLOSED; +option features.utf8_validation = NONE; option cc_enable_arenas = true; option optimize_for = LITE_RUNTIME; @@ -94,15 +96,17 @@ enum MapEnumLite { } message TestRequiredLite { - required int32 a = 1; - required int32 b = 2; - required int32 c = 3; + int32 a = 1 [features.field_presence = LEGACY_REQUIRED]; + + int32 b = 2 [features.field_presence = LEGACY_REQUIRED]; + + int32 c = 3 [features.field_presence = LEGACY_REQUIRED]; extend TestAllExtensionsLite { - optional TestRequiredLite single = 1000; + TestRequiredLite single = 1000; } } message ForeignMessageArenaLite { - optional int32 c = 1; + int32 c = 1; } diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index 0ce0218df9..fb0643c3d8 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -1308,6 +1308,14 @@ class PROTOBUF_EXPORT Reflection final { internal::ParseContext* ctx); }; +extern template void Reflection::SwapFieldsImpl( + Message* message1, Message* message2, + const std::vector& fields) const; + +extern template void Reflection::SwapFieldsImpl( + Message* message1, Message* message2, + const std::vector& fields) const; + // Abstract interface for a factory for message objects. // // The thread safety for this class is implementation dependent, see comments diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index f0ab785788..f32e929e8e 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc @@ -46,18 +46,22 @@ namespace google { namespace protobuf { -const char* MessageLite::_InternalParse(const char* ptr, - internal::ParseContext* ctx) { +const internal::TcParseTableBase* MessageLite::GetTcParseTable() const { auto* data = GetClassData(); ABSL_DCHECK(data != nullptr); auto* tc_table = data->tc_table; if (ABSL_PREDICT_FALSE(tc_table == nullptr)) { ABSL_DCHECK(!data->is_lite); - tc_table = data->full().descriptor_methods->get_tc_table(*this); + return data->full().descriptor_methods->get_tc_table(*this); } + return tc_table; +} - return internal::TcParser::ParseLoop(this, ptr, ctx, tc_table); +const char* MessageLite::_InternalParse(const char* ptr, + internal::ParseContext* ctx) { + return internal::TcParser::ParseLoopInlined(this, ptr, ctx, + GetTcParseTable()); } std::string MessageLite::GetTypeName() const { diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h index e7cdf17330..722bdf990e 100644 --- a/src/google/protobuf/message_lite.h +++ b/src/google/protobuf/message_lite.h @@ -126,6 +126,7 @@ class SwapFieldHelper; class ParseContext; struct DescriptorTable; +class DescriptorPoolExtensionFinder; class ExtensionSet; class LazyField; class RepeatedPtrFieldBase; @@ -516,6 +517,8 @@ class PROTOBUF_EXPORT MessageLite { return static_cast(Arena::CopyConstruct(arena, &from)); } + const internal::TcParseTableBase* GetTcParseTable() const; + inline explicit MessageLite(Arena* arena) : _internal_metadata_(arena) {} // We use a secondary vtable for descriptor based methods. This way ClassData @@ -660,6 +663,7 @@ class PROTOBUF_EXPORT MessageLite { friend class FastReflectionStringSetter; friend class Message; friend class Reflection; + friend class internal::DescriptorPoolExtensionFinder; friend class internal::ExtensionSet; friend class internal::LazyField; friend class internal::SwapFieldHelper; diff --git a/src/google/protobuf/message_unittest.inc b/src/google/protobuf/message_unittest.inc index 12d0e79b80..08b00a482f 100644 --- a/src/google/protobuf/message_unittest.inc +++ b/src/google/protobuf/message_unittest.inc @@ -1911,7 +1911,7 @@ TEST(MESSAGE_TEST_NAME, TestRepeatedStringParsers) { for (size_t i = 1; i <= encoded.size(); ++i) { TestInputStream input_stream(encoded, i); - auto& obj = *arena.CreateMessage(&arena); + auto& obj = *arena.Create(&arena); auto* ref = obj.GetReflection(); EXPECT_TRUE(obj.ParseFromZeroCopyStream(&input_stream)); if (field->is_repeated()) { diff --git a/src/google/protobuf/port.h b/src/google/protobuf/port.h index 91968ae657..73e08a21af 100644 --- a/src/google/protobuf/port.h +++ b/src/google/protobuf/port.h @@ -238,6 +238,15 @@ inline constexpr bool DebugHardenStringValues() { #endif } +// Returns true if force clearing oneof message on arena is enabled. +inline constexpr bool DebugHardenClearOneofMessageOnArena() { +#ifdef NDEBUG + return false; +#else + return true; +#endif +} + // Prefetch 5 64-byte cache line starting from 7 cache-lines ahead. // Constants are somewhat arbitrary and pretty aggressive, but were // chosen to give a better benchmark results. E.g. this is ~20% diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc index 27b148d82b..9e5a444778 100644 --- a/src/google/protobuf/port_def.inc +++ b/src/google/protobuf/port_def.inc @@ -367,18 +367,6 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), # define PROTOC_EXPORT #endif -#if defined(PROTOBUF_USE_DLLS) && defined(_MSC_VER) -# if defined(LIBPROTOBUF_TEST_EXPORTS) -# define PROTOBUF_TEST_EXPORTS __declspec(dllexport) -# else -# define PROTOBUF_TEST_EXPORTS __declspec(dllimport) -# endif // defined(LIBPROTOBUF_TEST_EXPORTS) -#elif defined(PROTOBUF_USE_DLLS) && defined(LIBPROTOBUF_TEST_EXPORTS) -# define PROTOBUF_TEST_EXPORTS __attribute__((visibility("default"))) -#else -# define PROTOBUF_TEST_EXPORTS -#endif - #if defined(PROTOBUF_PREDICT_TRUE) || defined(PROTOBUF_PREDICT_FALSE) #error PROTOBUF_PREDICT_(TRUE|FALSE) was previously defined #endif diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc index f8c0070b02..318f0f2873 100644 --- a/src/google/protobuf/proto3_arena_unittest.cc +++ b/src/google/protobuf/proto3_arena_unittest.cc @@ -10,9 +10,11 @@ #include #include +#include "absl/log/absl_check.h" #include "absl/strings/match.h" #include "google/protobuf/arena.h" -#include "google/protobuf/test_util.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/port.h" #include "google/protobuf/text_format.h" #include "google/protobuf/unittest.pb.h" #include "google/protobuf/unittest_proto3_arena.pb.h" @@ -255,6 +257,38 @@ TEST(Proto3OptionalTest, OptionalFields) { EXPECT_EQ(serialized.size(), 0); } +TEST(Proto3ArenaTest, CheckMessageFieldIsCleared) { + Arena arena; + auto msg = Arena::Create(&arena); + + // Referring to a saved pointer to a child message is never guaranteed to + // work. IOW, protobufs do not guarantee pointer stability. This test only + // does this to replicate (unsupported) user behaviors. + auto child = msg->mutable_optional_foreign_message(); + child->set_c(100); + msg->Clear(); + + EXPECT_EQ(child->c(), 0); +} + +TEST(Proto3ArenaTest, CheckOneofMessageFieldIsCleared) { + if (!internal::DebugHardenClearOneofMessageOnArena()) { + GTEST_SKIP() << "arena allocated oneof message fields are not cleared."; + } + + Arena arena; + auto msg = Arena::Create(&arena); + + // Referring to a saved pointer to a child message is never guaranteed to + // work. IOW, protobufs do not guarantee pointer stability. This test only + // does this to replicate (unsupported) user behaviors. + auto child = msg->mutable_oneof_nested_message(); + child->set_bb(100); + msg->Clear(); + + EXPECT_EQ(child->bb(), 0); +} + TEST(Proto3OptionalTest, OptionalFieldDescriptor) { const Descriptor* d = protobuf_unittest::TestProto3Optional::descriptor(); diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc index cbb03d53c1..8a5b799484 100644 --- a/src/google/protobuf/source_context.pb.cc +++ b/src/google/protobuf/source_context.pb.cc @@ -6,6 +6,7 @@ #include "google/protobuf/source_context.pb.h" #include +#include #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" @@ -154,6 +155,7 @@ SourceContext::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(SourceContext, _impl_._cached_size_), false, @@ -304,8 +306,8 @@ namespace protobuf { } // namespace protobuf } // namespace google // @@protoc_insertion_point(global_scope) -PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 -static ::std::false_type _static_init_ PROTOBUF_UNUSED = - (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto), - ::std::false_type{}); +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ PROTOBUF_UNUSED = + (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto), + ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/string_block.h b/src/google/protobuf/string_block.h index d6b1d1e499..2bd1a1caff 100644 --- a/src/google/protobuf/string_block.h +++ b/src/google/protobuf/string_block.h @@ -82,35 +82,37 @@ class alignas(std::string) StringBlock { size_t effective_size() const; private: + using size_type = uint16_t; + static_assert(alignof(std::string) <= sizeof(void*), ""); static_assert(alignof(std::string) <= ArenaAlignDefault::align, ""); ~StringBlock() = default; - explicit StringBlock(StringBlock* next, bool heap_allocated, uint32_t size, - uint32_t next_size) noexcept + explicit StringBlock(StringBlock* next, bool heap_allocated, size_type size, + size_type next_size) noexcept : next_(next), - heap_allocated_(heap_allocated), allocated_size_(size), - next_size_(next_size) {} + next_size_(next_size), + heap_allocated_(heap_allocated) {} - static constexpr uint32_t min_size() { return size_t{256}; } - static constexpr uint32_t max_size() { return size_t{8192}; } + static constexpr size_type min_size() { return size_type{256}; } + static constexpr size_type max_size() { return size_type{8192}; } // Returns `size` rounded down such that we can fit a perfect number // of std::string instances inside a StringBlock of that size. - static constexpr uint32_t RoundedSize(uint32_t size); + static constexpr size_type RoundedSize(size_type size); // Returns the size of the next block. size_t next_size() const { return next_size_; } StringBlock* const next_; - const bool heap_allocated_ : 1; - const uint32_t allocated_size_ : 31; - const uint32_t next_size_; + const size_type allocated_size_; + const size_type next_size_; + const bool heap_allocated_; }; -constexpr uint32_t StringBlock::RoundedSize(uint32_t size) { +constexpr StringBlock::size_type StringBlock::RoundedSize(size_type size) { return size - (size - sizeof(StringBlock)) % sizeof(std::string); } @@ -119,10 +121,10 @@ inline size_t StringBlock::NextSize(StringBlock* block) { } inline StringBlock* StringBlock::Emplace(void* p, size_t n, StringBlock* next) { - const auto count = static_cast(n); + const auto count = static_cast(n); ABSL_DCHECK_EQ(count, NextSize(next)); - uint32_t doubled = count * 2; - uint32_t next_size = next ? std::min(doubled, max_size()) : min_size(); + size_type doubled = count * 2; + size_type next_size = next ? std::min(doubled, max_size()) : min_size(); return new (p) StringBlock(next, false, RoundedSize(count), next_size); } @@ -130,11 +132,11 @@ inline StringBlock* StringBlock::New(StringBlock* next) { // Compute required size, rounding down to a multiple of sizeof(std:string) // so that we can optimize the allocation path. I.e., we incur a (constant // size) MOD() operation cost here to avoid any MUL() later on. - uint32_t size = min_size(); - uint32_t next_size = min_size(); + size_type size = min_size(); + size_type next_size = min_size(); if (next) { size = next->next_size_; - next_size = std::min(size * 2, max_size()); + next_size = std::min(size * 2, max_size()); } size = RoundedSize(size); void* p = ::operator new(size); diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc index b27f1b570c..4286dc5434 100644 --- a/src/google/protobuf/struct.pb.cc +++ b/src/google/protobuf/struct.pb.cc @@ -6,6 +6,7 @@ #include "google/protobuf/struct.pb.h" #include +#include #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" @@ -219,6 +220,7 @@ Struct_FieldsEntry_DoNotUse::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + nullptr, // tc_table nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Struct_FieldsEntry_DoNotUse, _cached_size_), false, @@ -283,6 +285,7 @@ Struct::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Struct, _impl_._cached_size_), false, @@ -570,12 +573,20 @@ void Value::clear_kind() { case kStructValue: { if (GetArena() == nullptr) { delete _impl_.kind_.struct_value_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + if (_impl_.kind_.struct_value_ != nullptr) { + _impl_.kind_.struct_value_->Clear(); + } } break; } case kListValue: { if (GetArena() == nullptr) { delete _impl_.kind_.list_value_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + if (_impl_.kind_.list_value_ != nullptr) { + _impl_.kind_.list_value_->Clear(); + } } break; } @@ -592,6 +603,7 @@ Value::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Value, _impl_._cached_size_), false, @@ -914,6 +926,7 @@ ListValue::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(ListValue, _impl_._cached_size_), false, @@ -1061,8 +1074,8 @@ namespace protobuf { } // namespace protobuf } // namespace google // @@protoc_insertion_point(global_scope) -PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 -static ::std::false_type _static_init_ PROTOBUF_UNUSED = - (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fstruct_2eproto), - ::std::false_type{}); +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ PROTOBUF_UNUSED = + (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fstruct_2eproto), + ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h index 2dfeeca858..ad1b79f8c1 100644 --- a/src/google/protobuf/struct.pb.h +++ b/src/google/protobuf/struct.pb.h @@ -1019,6 +1019,10 @@ inline void Value::clear_struct_value() { if (kind_case() == kStructValue) { if (GetArena() == nullptr) { delete _impl_.kind_.struct_value_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + if (_impl_.kind_.struct_value_ != nullptr) { + _impl_.kind_.struct_value_->Clear(); + } } clear_has_kind(); } @@ -1096,6 +1100,10 @@ inline void Value::clear_list_value() { if (kind_case() == kListValue) { if (GetArena() == nullptr) { delete _impl_.kind_.list_value_; + } else if (::google::protobuf::internal::DebugHardenClearOneofMessageOnArena()) { + if (_impl_.kind_.list_value_ != nullptr) { + _impl_.kind_.list_value_->Clear(); + } } clear_has_kind(); } diff --git a/src/google/protobuf/thread_safe_arena.h b/src/google/protobuf/thread_safe_arena.h index b7199dd74b..b721229fe6 100644 --- a/src/google/protobuf/thread_safe_arena.h +++ b/src/google/protobuf/thread_safe_arena.h @@ -10,16 +10,16 @@ #ifndef GOOGLE_PROTOBUF_THREAD_SAFE_ARENA_H__ #define GOOGLE_PROTOBUF_THREAD_SAFE_ARENA_H__ -#include #include -#include +#include +#include #include -#include +#include +#include "absl/base/attributes.h" #include "absl/synchronization/mutex.h" #include "google/protobuf/arena_align.h" #include "google/protobuf/arena_allocation_policy.h" -#include "google/protobuf/arena_cleanup.h" #include "google/protobuf/arenaz_sampler.h" #include "google/protobuf/port.h" #include "google/protobuf/serial_arena.h" diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc index 0ebdfb65ab..ec076d429f 100644 --- a/src/google/protobuf/timestamp.pb.cc +++ b/src/google/protobuf/timestamp.pb.cc @@ -6,6 +6,7 @@ #include "google/protobuf/timestamp.pb.h" #include +#include #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" @@ -145,6 +146,7 @@ Timestamp::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Timestamp, _impl_._cached_size_), false, @@ -319,8 +321,8 @@ namespace protobuf { } // namespace protobuf } // namespace google // @@protoc_insertion_point(global_scope) -PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 -static ::std::false_type _static_init_ PROTOBUF_UNUSED = - (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2ftimestamp_2eproto), - ::std::false_type{}); +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ PROTOBUF_UNUSED = + (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2ftimestamp_2eproto), + ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc index 7e2c669458..dfb47487d7 100644 --- a/src/google/protobuf/type.pb.cc +++ b/src/google/protobuf/type.pb.cc @@ -6,6 +6,7 @@ #include "google/protobuf/type.pb.h" #include +#include #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" @@ -491,6 +492,7 @@ Type::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Type, _impl_._cached_size_), false, @@ -885,6 +887,7 @@ Field::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Field, _impl_._cached_size_), false, @@ -1338,6 +1341,7 @@ Enum::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Enum, _impl_._cached_size_), false, @@ -1689,6 +1693,7 @@ EnumValue::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(EnumValue, _impl_._cached_size_), false, @@ -1952,6 +1957,7 @@ Option::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Option, _impl_._cached_size_), false, @@ -2143,8 +2149,8 @@ namespace protobuf { } // namespace protobuf } // namespace google // @@protoc_insertion_point(global_scope) -PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 -static ::std::false_type _static_init_ PROTOBUF_UNUSED = - (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2ftype_2eproto), - ::std::false_type{}); +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ PROTOBUF_UNUSED = + (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2ftype_2eproto), + ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/unittest_features.proto b/src/google/protobuf/unittest_features.proto index c5a36e4be6..6814bcc53b 100644 --- a/src/google/protobuf/unittest_features.proto +++ b/src/google/protobuf/unittest_features.proto @@ -26,57 +26,76 @@ message TestMessage { } } +enum EnumFeature { + TEST_ENUM_FEATURE_UNKNOWN = 0; + VALUE1 = 1; + VALUE2 = 2; + VALUE3 = 3; + VALUE4 = 4; + VALUE5 = 5; + VALUE6 = 6; + VALUE7 = 7; + VALUE8 = 8; + VALUE9 = 9; + VALUE10 = 10; + VALUE11 = 11; + VALUE12 = 12; + VALUE13 = 13; + VALUE14 = 14; + VALUE15 = 15; +} + message TestFeatures { - optional int32 int_file_feature = 1 [ + optional EnumFeature file_feature = 1 [ retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, - edition_defaults = { edition: EDITION_PROTO2, value: "-2" }, - edition_defaults = { edition: EDITION_PROTO3, value: "-3" }, - edition_defaults = { edition: EDITION_2023, value: "1" }, - edition_defaults = { edition: EDITION_99997_TEST_ONLY, value: "2" }, - edition_defaults = { edition: EDITION_99998_TEST_ONLY, value: "3" } + edition_defaults = { edition: EDITION_PROTO2, value: "VALUE1" }, + edition_defaults = { edition: EDITION_PROTO3, value: "VALUE2" }, + edition_defaults = { edition: EDITION_2023, value: "VALUE3" }, + edition_defaults = { edition: EDITION_99997_TEST_ONLY, value: "VALUE4" }, + edition_defaults = { edition: EDITION_99998_TEST_ONLY, value: "VALUE5" } ]; - optional int32 int_extension_range_feature = 2 [ + optional EnumFeature extension_range_feature = 2 [ retention = RETENTION_RUNTIME, targets = TARGET_TYPE_EXTENSION_RANGE, - edition_defaults = { edition: EDITION_PROTO2, value: "1" } + edition_defaults = { edition: EDITION_PROTO2, value: "VALUE1" } ]; - optional int32 int_message_feature = 3 [ + optional EnumFeature message_feature = 3 [ retention = RETENTION_RUNTIME, targets = TARGET_TYPE_MESSAGE, - edition_defaults = { edition: EDITION_PROTO2, value: "1" } + edition_defaults = { edition: EDITION_PROTO2, value: "VALUE1" } ]; - optional int32 int_field_feature = 4 [ + optional EnumFeature field_feature = 4 [ retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, - edition_defaults = { edition: EDITION_PROTO2, value: "1" } + edition_defaults = { edition: EDITION_PROTO2, value: "VALUE1" } ]; - optional int32 int_oneof_feature = 5 [ + optional EnumFeature oneof_feature = 5 [ retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ONEOF, - edition_defaults = { edition: EDITION_PROTO2, value: "1" } + edition_defaults = { edition: EDITION_PROTO2, value: "VALUE1" } ]; - optional int32 int_enum_feature = 6 [ + optional EnumFeature enum_feature = 6 [ retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, - edition_defaults = { edition: EDITION_PROTO2, value: "1" } + edition_defaults = { edition: EDITION_PROTO2, value: "VALUE1" } ]; - optional int32 int_enum_entry_feature = 7 [ + optional EnumFeature enum_entry_feature = 7 [ retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM_ENTRY, - edition_defaults = { edition: EDITION_PROTO2, value: "1" } + edition_defaults = { edition: EDITION_PROTO2, value: "VALUE1" } ]; - optional int32 int_service_feature = 8 [ + optional EnumFeature service_feature = 8 [ retention = RETENTION_RUNTIME, targets = TARGET_TYPE_SERVICE, - edition_defaults = { edition: EDITION_PROTO2, value: "1" } + edition_defaults = { edition: EDITION_PROTO2, value: "VALUE1" } ]; - optional int32 int_method_feature = 9 [ + optional EnumFeature method_feature = 9 [ retention = RETENTION_RUNTIME, targets = TARGET_TYPE_METHOD, - edition_defaults = { edition: EDITION_PROTO2, value: "1" } + edition_defaults = { edition: EDITION_PROTO2, value: "VALUE1" } ]; - optional int32 int_multiple_feature = 10 [ + optional EnumFeature multiple_feature = 10 [ retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, targets = TARGET_TYPE_FIELD, @@ -87,7 +106,7 @@ message TestFeatures { targets = TARGET_TYPE_METHOD, targets = TARGET_TYPE_ONEOF, targets = TARGET_TYPE_EXTENSION_RANGE, - edition_defaults = { edition: EDITION_PROTO2, value: "1" } + edition_defaults = { edition: EDITION_PROTO2, value: "VALUE1" } ]; optional bool bool_field_feature = 11 [ @@ -96,64 +115,8 @@ message TestFeatures { edition_defaults = { edition: EDITION_PROTO2, value: "false" }, edition_defaults = { edition: EDITION_99997_TEST_ONLY, value: "true" } ]; - optional float float_field_feature = 12 [ - retention = RETENTION_RUNTIME, - targets = TARGET_TYPE_FIELD, - edition_defaults = { edition: EDITION_PROTO2, value: "1.1" }, - edition_defaults = { edition: EDITION_99997_TEST_ONLY, value: "1.2" } - ]; - - message MessageFeature { - optional bool bool_field = 1; - optional int32 int_field = 2; - optional float float_field = 3; - optional string string_field = 4; - } - optional MessageFeature message_field_feature = 13 [ - retention = RETENTION_RUNTIME, - targets = TARGET_TYPE_FIELD, - edition_defaults = { - edition: EDITION_99997_TEST_ONLY, - value: "int_field: 2" - }, - edition_defaults = { - edition: EDITION_99998_TEST_ONLY, - value: "string_field: '2024'" - }, - edition_defaults = { - edition: EDITION_2023, - value: "bool_field: true int_field: 1 float_field: 1.5 string_field: '2023'" - }, - edition_defaults = { edition: EDITION_PROTO2, value: "" } - ]; - - enum EnumFeature { - TEST_ENUM_FEATURE_UNKNOWN = 0; - ENUM_VALUE1 = 1; - ENUM_VALUE2 = 2; - ENUM_VALUE3 = 3; - ENUM_VALUE4 = 4; - ENUM_VALUE5 = 5; - } - optional EnumFeature enum_field_feature = 14 [ - retention = RETENTION_RUNTIME, - targets = TARGET_TYPE_FIELD, - edition_defaults = { - edition: EDITION_PROTO2, - value: "TEST_ENUM_FEATURE_UNKNOWN" - }, - edition_defaults = { edition: EDITION_2023, value: "ENUM_VALUE1" }, - edition_defaults = { - edition: EDITION_99997_TEST_ONLY, - value: "ENUM_VALUE2" - }, - edition_defaults = { - edition: EDITION_99998_TEST_ONLY, - value: "ENUM_VALUE3" - } - ]; - optional int32 int_source_feature = 15 [ + optional EnumFeature source_feature = 15 [ retention = RETENTION_SOURCE, targets = TARGET_TYPE_FILE, targets = TARGET_TYPE_FIELD, @@ -164,10 +127,10 @@ message TestFeatures { targets = TARGET_TYPE_METHOD, targets = TARGET_TYPE_ONEOF, targets = TARGET_TYPE_EXTENSION_RANGE, - edition_defaults = { edition: EDITION_PROTO2, value: "1" } + edition_defaults = { edition: EDITION_PROTO2, value: "VALUE1" } ]; - optional string string_source_feature = 16 [ + optional EnumFeature source_feature2 = 16 [ retention = RETENTION_SOURCE, targets = TARGET_TYPE_FILE, targets = TARGET_TYPE_FIELD, @@ -178,6 +141,6 @@ message TestFeatures { targets = TARGET_TYPE_METHOD, targets = TARGET_TYPE_ONEOF, targets = TARGET_TYPE_EXTENSION_RANGE, - edition_defaults = { edition: EDITION_PROTO2, value: "'2023'" } + edition_defaults = { edition: EDITION_PROTO2, value: "VALUE1" } ]; } diff --git a/src/google/protobuf/unittest_import_lite.proto b/src/google/protobuf/unittest_import_lite.proto index 08a2dfa0ef..88cce29932 100644 --- a/src/google/protobuf/unittest_import_lite.proto +++ b/src/google/protobuf/unittest_import_lite.proto @@ -9,7 +9,7 @@ // // This is like unittest_import.proto but with optimize_for = LITE_RUNTIME. -syntax = "proto2"; +edition = "2023"; package protobuf_unittest_import; @@ -19,10 +19,12 @@ option optimize_for = LITE_RUNTIME; option java_package = "com.google.protobuf"; message ImportMessageLite { - optional int32 d = 1; + int32 d = 1; } enum ImportEnumLite { + option features.enum_type = CLOSED; + IMPORT_LITE_FOO = 7; IMPORT_LITE_BAR = 8; IMPORT_LITE_BAZ = 9; diff --git a/src/google/protobuf/unittest_import_public_lite.proto b/src/google/protobuf/unittest_import_public_lite.proto index 444c986a5d..30172833d6 100644 --- a/src/google/protobuf/unittest_import_public_lite.proto +++ b/src/google/protobuf/unittest_import_public_lite.proto @@ -7,7 +7,7 @@ // Author: liujisi@google.com (Pherl Liu) -syntax = "proto2"; +edition = "2023"; package protobuf_unittest_import; @@ -15,5 +15,5 @@ option optimize_for = LITE_RUNTIME; option java_package = "com.google.protobuf"; message PublicImportMessageLite { - optional int32 e = 1; + int32 e = 1; } diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto index 39ee8c1d9a..b3fcfa431c 100644 --- a/src/google/protobuf/unittest_lite.proto +++ b/src/google/protobuf/unittest_lite.proto @@ -9,12 +9,15 @@ // // This is like unittest.proto but with optimize_for = LITE_RUNTIME. -syntax = "proto2"; +edition = "2023"; package protobuf_unittest; import "google/protobuf/unittest_import_lite.proto"; +option features.enum_type = CLOSED; +option features.repeated_field_encoding = EXPANDED; +option features.utf8_validation = NONE; option cc_enable_arenas = true; option optimize_for = LITE_RUNTIME; option java_package = "com.google.protobuf"; @@ -22,13 +25,13 @@ option java_package = "com.google.protobuf"; // Same as TestAllTypes but with the lite runtime. message TestAllTypesLite { message NestedMessage { - optional int32 bb = 1; - optional int64 cc = 2; - repeated int32 dd = 3 [packed = true]; + int32 bb = 1; + int64 cc = 2; + repeated int32 dd = 3 [features.repeated_field_encoding = PACKED]; } message NestedMessage2 { - optional int32 dd = 1; + int32 dd = 1; } enum NestedEnum { @@ -38,45 +41,44 @@ message TestAllTypesLite { } // Singular - optional int32 optional_int32 = 1; - optional int64 optional_int64 = 2; - optional uint32 optional_uint32 = 3; - optional uint64 optional_uint64 = 4; - optional sint32 optional_sint32 = 5; - optional sint64 optional_sint64 = 6; - optional fixed32 optional_fixed32 = 7; - optional fixed64 optional_fixed64 = 8; - optional sfixed32 optional_sfixed32 = 9; - optional sfixed64 optional_sfixed64 = 10; - optional float optional_float = 11; - optional double optional_double = 12; - optional bool optional_bool = 13; - optional string optional_string = 14; - optional bytes optional_bytes = 15; - - optional group OptionalGroup = 16 { - optional int32 a = 17; + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + sint32 optional_sint32 = 5; + sint64 optional_sint64 = 6; + fixed32 optional_fixed32 = 7; + fixed64 optional_fixed64 = 8; + sfixed32 optional_sfixed32 = 9; + sfixed64 optional_sfixed64 = 10; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; + + message OptionalGroup { + int32 a = 17; } - optional NestedMessage optional_nested_message = 18; - optional ForeignMessageLite optional_foreign_message = 19; - optional protobuf_unittest_import.ImportMessageLite optional_import_message = - 20; + OptionalGroup optionalgroup = 16 [features.message_encoding = DELIMITED]; - optional NestedEnum optional_nested_enum = 21; - optional ForeignEnumLite optional_foreign_enum = 22; - optional protobuf_unittest_import.ImportEnumLite optional_import_enum = 23; + NestedMessage optional_nested_message = 18; + ForeignMessageLite optional_foreign_message = 19; + protobuf_unittest_import.ImportMessageLite optional_import_message = 20; + NestedEnum optional_nested_enum = 21; + ForeignEnumLite optional_foreign_enum = 22; + protobuf_unittest_import.ImportEnumLite optional_import_enum = 23; + string optional_string_piece = 24 [ctype = STRING_PIECE]; - optional string optional_string_piece = 24 [ctype = STRING_PIECE]; - optional string optional_cord = 25 [ctype = CORD]; + string optional_cord = 25 [ctype = CORD]; // Defined in unittest_import_public.proto - optional protobuf_unittest_import.PublicImportMessageLite + protobuf_unittest_import.PublicImportMessageLite optional_public_import_message = 26; + NestedMessage optional_lazy_message = 27 [lazy = true]; - optional NestedMessage optional_lazy_message = 27 [lazy = true]; - optional NestedMessage optional_unverified_lazy_message = 28 - [unverified_lazy = true]; + NestedMessage optional_unverified_lazy_message = 28 [unverified_lazy = true]; // Repeated repeated int32 repeated_int32 = 31; @@ -95,50 +97,67 @@ message TestAllTypesLite { repeated string repeated_string = 44; repeated bytes repeated_bytes = 45; - repeated group RepeatedGroup = 46 { - optional int32 a = 47; + message RepeatedGroup { + int32 a = 47; } + repeated RepeatedGroup repeatedgroup = 46 + [features.message_encoding = DELIMITED]; + repeated NestedMessage repeated_nested_message = 48; repeated ForeignMessageLite repeated_foreign_message = 49; repeated protobuf_unittest_import.ImportMessageLite repeated_import_message = 50; - repeated NestedEnum repeated_nested_enum = 51; repeated ForeignEnumLite repeated_foreign_enum = 52; repeated protobuf_unittest_import.ImportEnumLite repeated_import_enum = 53; - repeated string repeated_string_piece = 54 [ctype = STRING_PIECE]; + repeated string repeated_cord = 55 [ctype = CORD]; - repeated NestedMessage repeated_lazy_message = 57 ; + repeated NestedMessage repeated_lazy_message = 57; // Singular with defaults - optional int32 default_int32 = 61 [default = 41]; - optional int64 default_int64 = 62 [default = 42]; - optional uint32 default_uint32 = 63 [default = 43]; - optional uint64 default_uint64 = 64 [default = 44]; - optional sint32 default_sint32 = 65 [default = -45]; - optional sint64 default_sint64 = 66 [default = 46]; - optional fixed32 default_fixed32 = 67 [default = 47]; - optional fixed64 default_fixed64 = 68 [default = 48]; - optional sfixed32 default_sfixed32 = 69 [default = 49]; - optional sfixed64 default_sfixed64 = 70 [default = -50]; - optional float default_float = 71 [default = 51.5]; - optional double default_double = 72 [default = 52e3]; - optional bool default_bool = 73 [default = true]; - optional string default_string = 74 [default = "hello"]; - optional bytes default_bytes = 75 [default = "world"]; - - optional NestedEnum default_nested_enum = 81 [default = BAR]; - optional ForeignEnumLite default_foreign_enum = 82 - [default = FOREIGN_LITE_BAR]; - optional protobuf_unittest_import.ImportEnumLite default_import_enum = 83 + int32 default_int32 = 61 [default = 41]; + + int64 default_int64 = 62 [default = 42]; + + uint32 default_uint32 = 63 [default = 43]; + + uint64 default_uint64 = 64 [default = 44]; + + sint32 default_sint32 = 65 [default = -45]; + + sint64 default_sint64 = 66 [default = 46]; + + fixed32 default_fixed32 = 67 [default = 47]; + + fixed64 default_fixed64 = 68 [default = 48]; + + sfixed32 default_sfixed32 = 69 [default = 49]; + + sfixed64 default_sfixed64 = 70 [default = -50]; + + float default_float = 71 [default = 51.5]; + + double default_double = 72 [default = 5.2e4]; + + bool default_bool = 73 [default = true]; + + string default_string = 74 [default = "hello"]; + + bytes default_bytes = 75 [default = "world"]; + + NestedEnum default_nested_enum = 81 [default = BAR]; + + ForeignEnumLite default_foreign_enum = 82 [default = FOREIGN_LITE_BAR]; + + protobuf_unittest_import.ImportEnumLite default_import_enum = 83 [default = IMPORT_LITE_BAR]; - optional string default_string_piece = 84 - [ctype = STRING_PIECE, default = "abc"]; - optional string default_cord = 85 [ctype = CORD, default = "123"]; + string default_string_piece = 84 [ctype = STRING_PIECE, default = "abc"]; + + string default_cord = 85 [ctype = CORD, default = "123"]; // For oneof test oneof oneof_field { @@ -147,15 +166,16 @@ message TestAllTypesLite { string oneof_string = 113; bytes oneof_bytes = 114; NestedMessage oneof_lazy_nested_message = 115 [lazy = true]; + NestedMessage2 oneof_nested_message2 = 117; } // Tests toString for non-repeated fields with a list suffix - optional int32 deceptively_named_list = 116; + int32 deceptively_named_list = 116; } message ForeignMessageLite { - optional int32 c = 1; + int32 c = 1; } enum ForeignEnumLite { @@ -165,20 +185,43 @@ enum ForeignEnumLite { } message TestPackedTypesLite { - repeated int32 packed_int32 = 90 [packed = true]; - repeated int64 packed_int64 = 91 [packed = true]; - repeated uint32 packed_uint32 = 92 [packed = true]; - repeated uint64 packed_uint64 = 93 [packed = true]; - repeated sint32 packed_sint32 = 94 [packed = true]; - repeated sint64 packed_sint64 = 95 [packed = true]; - repeated fixed32 packed_fixed32 = 96 [packed = true]; - repeated fixed64 packed_fixed64 = 97 [packed = true]; - repeated sfixed32 packed_sfixed32 = 98 [packed = true]; - repeated sfixed64 packed_sfixed64 = 99 [packed = true]; - repeated float packed_float = 100 [packed = true]; - repeated double packed_double = 101 [packed = true]; - repeated bool packed_bool = 102 [packed = true]; - repeated ForeignEnumLite packed_enum = 103 [packed = true]; + repeated int32 packed_int32 = 90 [features.repeated_field_encoding = PACKED]; + + repeated int64 packed_int64 = 91 [features.repeated_field_encoding = PACKED]; + + repeated uint32 packed_uint32 = 92 + [features.repeated_field_encoding = PACKED]; + + repeated uint64 packed_uint64 = 93 + [features.repeated_field_encoding = PACKED]; + + repeated sint32 packed_sint32 = 94 + [features.repeated_field_encoding = PACKED]; + + repeated sint64 packed_sint64 = 95 + [features.repeated_field_encoding = PACKED]; + + repeated fixed32 packed_fixed32 = 96 + [features.repeated_field_encoding = PACKED]; + + repeated fixed64 packed_fixed64 = 97 + [features.repeated_field_encoding = PACKED]; + + repeated sfixed32 packed_sfixed32 = 98 + [features.repeated_field_encoding = PACKED]; + + repeated sfixed64 packed_sfixed64 = 99 + [features.repeated_field_encoding = PACKED]; + + repeated float packed_float = 100 [features.repeated_field_encoding = PACKED]; + + repeated double packed_double = 101 + [features.repeated_field_encoding = PACKED]; + + repeated bool packed_bool = 102 [features.repeated_field_encoding = PACKED]; + + repeated ForeignEnumLite packed_enum = 103 + [features.repeated_field_encoding = PACKED]; } message TestAllExtensionsLite { @@ -187,49 +230,43 @@ message TestAllExtensionsLite { extend TestAllExtensionsLite { // Singular - optional int32 optional_int32_extension_lite = 1; - optional int64 optional_int64_extension_lite = 2; - optional uint32 optional_uint32_extension_lite = 3; - optional uint64 optional_uint64_extension_lite = 4; - optional sint32 optional_sint32_extension_lite = 5; - optional sint64 optional_sint64_extension_lite = 6; - optional fixed32 optional_fixed32_extension_lite = 7; - optional fixed64 optional_fixed64_extension_lite = 8; - optional sfixed32 optional_sfixed32_extension_lite = 9; - optional sfixed64 optional_sfixed64_extension_lite = 10; - optional float optional_float_extension_lite = 11; - optional double optional_double_extension_lite = 12; - optional bool optional_bool_extension_lite = 13; - optional string optional_string_extension_lite = 14; - optional bytes optional_bytes_extension_lite = 15; - - optional group OptionalGroup_extension_lite = 16 { - optional int32 a = 17; - } - - optional TestAllTypesLite.NestedMessage - optional_nested_message_extension_lite = 18; - optional ForeignMessageLite optional_foreign_message_extension_lite = 19; - optional protobuf_unittest_import.ImportMessageLite + int32 optional_int32_extension_lite = 1; + int64 optional_int64_extension_lite = 2; + uint32 optional_uint32_extension_lite = 3; + uint64 optional_uint64_extension_lite = 4; + sint32 optional_sint32_extension_lite = 5; + sint64 optional_sint64_extension_lite = 6; + fixed32 optional_fixed32_extension_lite = 7; + fixed64 optional_fixed64_extension_lite = 8; + sfixed32 optional_sfixed32_extension_lite = 9; + sfixed64 optional_sfixed64_extension_lite = 10; + float optional_float_extension_lite = 11; + double optional_double_extension_lite = 12; + bool optional_bool_extension_lite = 13; + string optional_string_extension_lite = 14; + bytes optional_bytes_extension_lite = 15; + OptionalGroup_extension_lite optionalgroup_extension_lite = 16 + [features.message_encoding = DELIMITED]; + + TestAllTypesLite.NestedMessage optional_nested_message_extension_lite = 18; + ForeignMessageLite optional_foreign_message_extension_lite = 19; + protobuf_unittest_import.ImportMessageLite optional_import_message_extension_lite = 20; + TestAllTypesLite.NestedEnum optional_nested_enum_extension_lite = 21; + ForeignEnumLite optional_foreign_enum_extension_lite = 22; + protobuf_unittest_import.ImportEnumLite optional_import_enum_extension_lite = + 23; + string optional_string_piece_extension_lite = 24 [ctype = STRING_PIECE]; - optional TestAllTypesLite.NestedEnum optional_nested_enum_extension_lite = 21; - optional ForeignEnumLite optional_foreign_enum_extension_lite = 22; - optional protobuf_unittest_import.ImportEnumLite - optional_import_enum_extension_lite = 23; - - optional string optional_string_piece_extension_lite = 24 - [ctype = STRING_PIECE]; // TODO: ctype=CORD is not supported for extension. Add // ctype=CORD option back after it is supported. - optional string optional_cord_extension_lite = 25; - - optional protobuf_unittest_import.PublicImportMessageLite + string optional_cord_extension_lite = 25; + protobuf_unittest_import.PublicImportMessageLite optional_public_import_message_extension_lite = 26; + TestAllTypesLite.NestedMessage optional_lazy_message_extension_lite = 27 + [lazy = true]; - optional TestAllTypesLite.NestedMessage optional_lazy_message_extension_lite = - 27 [lazy = true]; - optional TestAllTypesLite.NestedMessage + TestAllTypesLite.NestedMessage optional_unverified_lazy_message_extension_lite = 28 [unverified_lazy = true]; @@ -249,67 +286,87 @@ extend TestAllExtensionsLite { repeated bool repeated_bool_extension_lite = 43; repeated string repeated_string_extension_lite = 44; repeated bytes repeated_bytes_extension_lite = 45; - - repeated group RepeatedGroup_extension_lite = 46 { - optional int32 a = 47; - } + repeated RepeatedGroup_extension_lite repeatedgroup_extension_lite = 46 + [features.message_encoding = DELIMITED]; repeated TestAllTypesLite.NestedMessage repeated_nested_message_extension_lite = 48; repeated ForeignMessageLite repeated_foreign_message_extension_lite = 49; repeated protobuf_unittest_import.ImportMessageLite repeated_import_message_extension_lite = 50; - repeated TestAllTypesLite.NestedEnum repeated_nested_enum_extension_lite = 51; repeated ForeignEnumLite repeated_foreign_enum_extension_lite = 52; repeated protobuf_unittest_import.ImportEnumLite repeated_import_enum_extension_lite = 53; - repeated string repeated_string_piece_extension_lite = 54 [ctype = STRING_PIECE]; + // TODO: ctype=CORD is not supported for extension. Add // ctype=CORD option back after it is supported. repeated string repeated_cord_extension_lite = 55; - repeated TestAllTypesLite.NestedMessage repeated_lazy_message_extension_lite = 57 [lazy = true]; // Singular with defaults - optional int32 default_int32_extension_lite = 61 [default = 41]; - optional int64 default_int64_extension_lite = 62 [default = 42]; - optional uint32 default_uint32_extension_lite = 63 [default = 43]; - optional uint64 default_uint64_extension_lite = 64 [default = 44]; - optional sint32 default_sint32_extension_lite = 65 [default = -45]; - optional sint64 default_sint64_extension_lite = 66 [default = 46]; - optional fixed32 default_fixed32_extension_lite = 67 [default = 47]; - optional fixed64 default_fixed64_extension_lite = 68 [default = 48]; - optional sfixed32 default_sfixed32_extension_lite = 69 [default = 49]; - optional sfixed64 default_sfixed64_extension_lite = 70 [default = -50]; - optional float default_float_extension_lite = 71 [default = 51.5]; - optional double default_double_extension_lite = 72 [default = 52e3]; - optional bool default_bool_extension_lite = 73 [default = true]; - optional string default_string_extension_lite = 74 [default = "hello"]; - optional bytes default_bytes_extension_lite = 75 [default = "world"]; - - optional TestAllTypesLite.NestedEnum default_nested_enum_extension_lite = 81 + int32 default_int32_extension_lite = 61 [default = 41]; + + int64 default_int64_extension_lite = 62 [default = 42]; + + uint32 default_uint32_extension_lite = 63 [default = 43]; + + uint64 default_uint64_extension_lite = 64 [default = 44]; + + sint32 default_sint32_extension_lite = 65 [default = -45]; + + sint64 default_sint64_extension_lite = 66 [default = 46]; + + fixed32 default_fixed32_extension_lite = 67 [default = 47]; + + fixed64 default_fixed64_extension_lite = 68 [default = 48]; + + sfixed32 default_sfixed32_extension_lite = 69 [default = 49]; + + sfixed64 default_sfixed64_extension_lite = 70 [default = -50]; + + float default_float_extension_lite = 71 [default = 51.5]; + + double default_double_extension_lite = 72 [default = 5.2e4]; + + bool default_bool_extension_lite = 73 [default = true]; + + string default_string_extension_lite = 74 [default = "hello"]; + + bytes default_bytes_extension_lite = 75 [default = "world"]; + + TestAllTypesLite.NestedEnum default_nested_enum_extension_lite = 81 [default = BAR]; - optional ForeignEnumLite default_foreign_enum_extension_lite = 82 + + ForeignEnumLite default_foreign_enum_extension_lite = 82 [default = FOREIGN_LITE_BAR]; - optional protobuf_unittest_import.ImportEnumLite - default_import_enum_extension_lite = 83 [default = IMPORT_LITE_BAR]; - optional string default_string_piece_extension_lite = 84 + protobuf_unittest_import.ImportEnumLite default_import_enum_extension_lite = 83 + [default = IMPORT_LITE_BAR]; + + string default_string_piece_extension_lite = 84 [ctype = STRING_PIECE, default = "abc"]; + // TODO: ctype=CORD is not supported for extension. Add // ctype=CORD option back after it is supported. - optional string default_cord_extension_lite = 85 [default = "123"]; + string default_cord_extension_lite = 85 [default = "123"]; // For oneof test - optional uint32 oneof_uint32_extension_lite = 111; - optional TestAllTypesLite.NestedMessage oneof_nested_message_extension_lite = - 112; - optional string oneof_string_extension_lite = 113; - optional bytes oneof_bytes_extension_lite = 114; + uint32 oneof_uint32_extension_lite = 111; + TestAllTypesLite.NestedMessage oneof_nested_message_extension_lite = 112; + string oneof_string_extension_lite = 113; + bytes oneof_bytes_extension_lite = 114; +} + +message OptionalGroup_extension_lite { + int32 a = 17; +} + +message RepeatedGroup_extension_lite { + int32 a = 47; } message TestPackedExtensionsLite { @@ -317,35 +374,66 @@ message TestPackedExtensionsLite { } extend TestPackedExtensionsLite { - repeated int32 packed_int32_extension_lite = 90 [packed = true]; - repeated int64 packed_int64_extension_lite = 91 [packed = true]; - repeated uint32 packed_uint32_extension_lite = 92 [packed = true]; - repeated uint64 packed_uint64_extension_lite = 93 [packed = true]; - repeated sint32 packed_sint32_extension_lite = 94 [packed = true]; - repeated sint64 packed_sint64_extension_lite = 95 [packed = true]; - repeated fixed32 packed_fixed32_extension_lite = 96 [packed = true]; - repeated fixed64 packed_fixed64_extension_lite = 97 [packed = true]; - repeated sfixed32 packed_sfixed32_extension_lite = 98 [packed = true]; - repeated sfixed64 packed_sfixed64_extension_lite = 99 [packed = true]; - repeated float packed_float_extension_lite = 100 [packed = true]; - repeated double packed_double_extension_lite = 101 [packed = true]; - repeated bool packed_bool_extension_lite = 102 [packed = true]; - repeated ForeignEnumLite packed_enum_extension_lite = 103 [packed = true]; + repeated int32 packed_int32_extension_lite = 90 + [features.repeated_field_encoding = PACKED]; + + repeated int64 packed_int64_extension_lite = 91 + [features.repeated_field_encoding = PACKED]; + + repeated uint32 packed_uint32_extension_lite = 92 + [features.repeated_field_encoding = PACKED]; + + repeated uint64 packed_uint64_extension_lite = 93 + [features.repeated_field_encoding = PACKED]; + + repeated sint32 packed_sint32_extension_lite = 94 + [features.repeated_field_encoding = PACKED]; + + repeated sint64 packed_sint64_extension_lite = 95 + [features.repeated_field_encoding = PACKED]; + + repeated fixed32 packed_fixed32_extension_lite = 96 + [features.repeated_field_encoding = PACKED]; + + repeated fixed64 packed_fixed64_extension_lite = 97 + [features.repeated_field_encoding = PACKED]; + + repeated sfixed32 packed_sfixed32_extension_lite = 98 + [features.repeated_field_encoding = PACKED]; + + repeated sfixed64 packed_sfixed64_extension_lite = 99 + [features.repeated_field_encoding = PACKED]; + + repeated float packed_float_extension_lite = 100 + [features.repeated_field_encoding = PACKED]; + + repeated double packed_double_extension_lite = 101 + [features.repeated_field_encoding = PACKED]; + + repeated bool packed_bool_extension_lite = 102 + [features.repeated_field_encoding = PACKED]; + + repeated ForeignEnumLite packed_enum_extension_lite = 103 + [features.repeated_field_encoding = PACKED]; } message TestNestedExtensionLite { extend TestAllExtensionsLite { - optional int32 nested_extension = 12345; + int32 nested_extension = 12345; } } // Test that deprecated fields work. We only verify that they compile (at one // point this failed). message TestDeprecatedLite { - optional int32 deprecated_field = 1 [deprecated = true]; - required int32 deprecated_field2 = 2 [deprecated = true]; - optional string deprecated_field3 = 3 [deprecated = true]; - optional TestDeprecatedLite deprecated_field4 = 4 [deprecated = true]; + int32 deprecated_field = 1 [deprecated = true]; + + int32 deprecated_field2 = 2 + [features.field_presence = LEGACY_REQUIRED, deprecated = true]; + + string deprecated_field3 = 3 [deprecated = true]; + + TestDeprecatedLite deprecated_field4 = 4 [deprecated = true]; } // See the comments of the same type in unittest.proto. @@ -354,27 +442,46 @@ message TestParsingMergeLite { repeated TestAllTypesLite field1 = 1; repeated TestAllTypesLite field2 = 2; repeated TestAllTypesLite field3 = 3; - repeated group Group1 = 10 { - optional TestAllTypesLite field1 = 11; + + message Group1 { + TestAllTypesLite field1 = 11; } - repeated group Group2 = 20 { - optional TestAllTypesLite field1 = 21; + + repeated Group1 group1 = 10 [features.message_encoding = DELIMITED]; + + message Group2 { + TestAllTypesLite field1 = 21; } + + repeated Group2 group2 = 20 [features.message_encoding = DELIMITED]; + repeated TestAllTypesLite ext1 = 1000; repeated TestAllTypesLite ext2 = 1001; } - required TestAllTypesLite required_all_types = 1; - optional TestAllTypesLite optional_all_types = 2; + + TestAllTypesLite required_all_types = 1 + [features.field_presence = LEGACY_REQUIRED]; + + TestAllTypesLite optional_all_types = 2; repeated TestAllTypesLite repeated_all_types = 3; - optional group OptionalGroup = 10 { - optional TestAllTypesLite optional_group_all_types = 11; + + message OptionalGroup { + TestAllTypesLite optional_group_all_types = 11; } - repeated group RepeatedGroup = 20 { - optional TestAllTypesLite repeated_group_all_types = 21; + + OptionalGroup optionalgroup = 10 [features.message_encoding = DELIMITED]; + + message RepeatedGroup { + TestAllTypesLite repeated_group_all_types = 21; } + + repeated RepeatedGroup repeatedgroup = 20 + [features.message_encoding = DELIMITED]; + extensions 1000 to max; + extend TestParsingMergeLite { - optional TestAllTypesLite optional_ext = 1000; + TestAllTypesLite optional_ext = 1000; repeated TestAllTypesLite repeated_ext = 1001; } } @@ -382,7 +489,7 @@ message TestParsingMergeLite { // Test that the correct exception is thrown by parseFrom in a corner case // involving merging, extensions, and required fields. message TestMergeExceptionLite { - optional TestAllExtensionsLite all_extensions = 1; + TestAllExtensionsLite all_extensions = 1; } // TestEmptyMessageLite is used to test unknown fields support in lite mode. @@ -404,30 +511,36 @@ enum V2EnumLite { } message V1MessageLite { - required int32 int_field = 1; - optional V1EnumLite enum_field = 2 [default = V1_FIRST]; + int32 int_field = 1 [features.field_presence = LEGACY_REQUIRED]; + + V1EnumLite enum_field = 2 [default = V1_FIRST]; } message V2MessageLite { - required int32 int_field = 1; - optional V2EnumLite enum_field = 2 [default = V2_FIRST]; + int32 int_field = 1 [features.field_presence = LEGACY_REQUIRED]; + + V2EnumLite enum_field = 2 [default = V2_FIRST]; } message TestHugeFieldNumbersLite { - optional int32 optional_int32 = 536870000; - optional int32 fixed_32 = 536870001; - repeated int32 repeated_int32 = 536870002 [packed = false]; - repeated int32 packed_int32 = 536870003 [packed = true]; - - optional ForeignEnumLite optional_enum = 536870004; - optional string optional_string = 536870005; - optional bytes optional_bytes = 536870006; - optional ForeignMessageLite optional_message = 536870007; - - optional group OptionalGroup = 536870008 { - optional int32 group_a = 536870009; + int32 optional_int32 = 536870000; + int32 fixed_32 = 536870001; + repeated int32 repeated_int32 = 536870002; + repeated int32 packed_int32 = 536870003 + [features.repeated_field_encoding = PACKED]; + + ForeignEnumLite optional_enum = 536870004; + string optional_string = 536870005; + bytes optional_bytes = 536870006; + ForeignMessageLite optional_message = 536870007; + + message OptionalGroup { + int32 group_a = 536870009; } + OptionalGroup optionalgroup = 536870008 + [features.message_encoding = DELIMITED]; + map string_string_map = 536870010; oneof oneof_field { @@ -445,7 +558,7 @@ message TestHugeFieldNumbersLite { } extend TestHugeFieldNumbersLite { - optional TestAllTypesLite test_all_types_lite = 536860000; + TestAllTypesLite test_all_types_lite = 536860000; } message TestOneofParsingLite { @@ -454,11 +567,16 @@ message TestOneofParsingLite { TestAllTypesLite oneof_submessage = 2; string oneof_string = 3; bytes oneof_bytes = 4 [default = "default bytes"]; + string oneof_string_cord = 5 [ctype = CORD, default = "default Cord"]; + bytes oneof_bytes_cord = 6 [ctype = CORD]; + string oneof_string_string_piece = 7 [ctype = STRING_PIECE]; + bytes oneof_bytes_string_piece = 8 [ctype = STRING_PIECE, default = "default StringPiece"]; + V2EnumLite oneof_enum = 9; } } @@ -473,7 +591,8 @@ message TestMessageSetLite { // packed and non-packed repeated fields. We use the field number 2048, because // that is large enough to require a 3-byte varint for the tag. message PackedInt32 { - repeated int32 repeated_int32 = 2048 [packed = true]; + repeated int32 repeated_int32 = 2048 + [features.repeated_field_encoding = PACKED]; } message NonPackedInt32 { @@ -481,7 +600,8 @@ message NonPackedInt32 { } message PackedFixed32 { - repeated fixed32 repeated_fixed32 = 2048 [packed = true]; + repeated fixed32 repeated_fixed32 = 2048 + [features.repeated_field_encoding = PACKED]; } message NonPackedFixed32 { @@ -502,6 +622,6 @@ message DupEnum { } message RecursiveMessage { - optional RecursiveMessage recurse = 1; - optional bytes payload = 2; + RecursiveMessage recurse = 1; + bytes payload = 2; } diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc index fd2b0eb189..4bfd901c6d 100644 --- a/src/google/protobuf/wrappers.pb.cc +++ b/src/google/protobuf/wrappers.pb.cc @@ -6,6 +6,7 @@ #include "google/protobuf/wrappers.pb.h" #include +#include #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" @@ -388,6 +389,7 @@ DoubleValue::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(DoubleValue, _impl_._cached_size_), false, @@ -578,6 +580,7 @@ FloatValue::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(FloatValue, _impl_._cached_size_), false, @@ -768,6 +771,7 @@ Int64Value::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Int64Value, _impl_._cached_size_), false, @@ -944,6 +948,7 @@ UInt64Value::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(UInt64Value, _impl_._cached_size_), false, @@ -1120,6 +1125,7 @@ Int32Value::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(Int32Value, _impl_._cached_size_), false, @@ -1296,6 +1302,7 @@ UInt32Value::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(UInt32Value, _impl_._cached_size_), false, @@ -1472,6 +1479,7 @@ BoolValue::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(BoolValue, _impl_._cached_size_), false, @@ -1661,6 +1669,7 @@ StringValue::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(StringValue, _impl_._cached_size_), false, @@ -1857,6 +1866,7 @@ BytesValue::GetClassData() const { PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: ClassDataFull _data_ = { { + &_table_.header, nullptr, // OnDemandRegisterArenaDtor PROTOBUF_FIELD_OFFSET(BytesValue, _impl_._cached_size_), false, @@ -2002,8 +2012,8 @@ namespace protobuf { } // namespace protobuf } // namespace google // @@protoc_insertion_point(global_scope) -PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 -static ::std::false_type _static_init_ PROTOBUF_UNUSED = - (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fwrappers_2eproto), - ::std::false_type{}); +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ PROTOBUF_UNUSED = + (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fwrappers_2eproto), + ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/upb/mem/arena.c b/upb/mem/arena.c index 93069805b3..fc65f69013 100644 --- a/upb/mem/arena.c +++ b/upb/mem/arena.c @@ -7,6 +7,10 @@ #include "upb/mem/arena.h" +#ifdef UPB_TRACING_ENABLED +#include +#endif + #include #include @@ -117,6 +121,38 @@ static bool _upb_ArenaInternal_HasInitialBlock(upb_ArenaInternal* ai) { return ai->block_alloc & 0x1; } +#ifdef UPB_TRACING_ENABLED +static void (*_init_arena_trace_handler)(const upb_Arena*, size_t size) = NULL; +static void (*_fuse_arena_trace_handler)(const upb_Arena*, + const upb_Arena*) = NULL; +static void (*_free_arena_trace_handler)(const upb_Arena*) = NULL; + +void upb_Arena_SetTraceHandler( + void (*initArenaTraceHandler)(const upb_Arena*, size_t size), + void (*fuseArenaTraceHandler)(const upb_Arena*, const upb_Arena*), + void (*freeArenaTraceHandler)(const upb_Arena*)) { + _init_arena_trace_handler = initArenaTraceHandler; + _fuse_arena_trace_handler = fuseArenaTraceHandler; + _free_arena_trace_handler = freeArenaTraceHandler; +} + +void upb_Arena_LogInit(const upb_Arena* arena, size_t size) { + if (_init_arena_trace_handler) { + _init_arena_trace_handler(arena, size); + } +} +void upb_Arena_LogFuse(const upb_Arena* arena1, const upb_Arena* arena2) { + if (_fuse_arena_trace_handler) { + _fuse_arena_trace_handler(arena1, arena2); + } +} +void upb_Arena_LogFree(const upb_Arena* arena) { + if (_free_arena_trace_handler) { + _free_arena_trace_handler(arena); + } +} +#endif // UPB_TRACING_ENABLED + static upb_ArenaRoot _upb_Arena_FindRoot(upb_Arena* a) { upb_ArenaInternal* ai = upb_Arena_Internal(a); uintptr_t poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); @@ -280,7 +316,13 @@ upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) { n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_ArenaState)); if (UPB_UNLIKELY(n < sizeof(upb_ArenaState))) { +#ifdef UPB_TRACING_ENABLED + upb_Arena* ret = _upb_Arena_InitSlow(alloc); + upb_Arena_LogInit(ret, n); + return ret; +#else return _upb_Arena_InitSlow(alloc); +#endif } a = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), upb_ArenaState); @@ -293,13 +335,14 @@ upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) { a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 1); a->head.UPB_PRIVATE(ptr) = mem; a->head.UPB_PRIVATE(end) = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), char); - +#ifdef UPB_TRACING_ENABLED + upb_Arena_LogInit(&a->head, n); +#endif return &a->head; } static void _upb_Arena_DoFree(upb_ArenaInternal* ai) { UPB_ASSERT(_upb_Arena_RefCountFromTagged(ai->parent_or_count) == 1); - while (ai != NULL) { // Load first since arena itself is likely from one of its blocks. upb_ArenaInternal* next_arena = @@ -330,6 +373,9 @@ retry: // expensive then direct loads. As an optimization, we only do RMW ops // when we need to update things for other threads to see. if (poc == _upb_Arena_TaggedFromRefcount(1)) { +#ifdef UPB_TRACING_ENABLED + upb_Arena_LogFree(a); +#endif _upb_Arena_DoFree(ai); return; } @@ -449,6 +495,10 @@ static bool _upb_Arena_FixupRefs(upb_ArenaInternal* new_root, bool upb_Arena_Fuse(upb_Arena* a1, upb_Arena* a2) { if (a1 == a2) return true; // trivial fuse +#ifdef UPB_TRACING_ENABLED + upb_Arena_LogFuse(a1, a2); +#endif + upb_ArenaInternal* ai1 = upb_Arena_Internal(a1); upb_ArenaInternal* ai2 = upb_Arena_Internal(a2); diff --git a/upb/mem/arena.h b/upb/mem/arena.h index 761d79743d..83f5781f83 100644 --- a/upb/mem/arena.h +++ b/upb/mem/arena.h @@ -65,6 +65,14 @@ UPB_API_INLINE void* upb_Arena_Realloc(upb_Arena* a, void* ptr, size_t oldsize, UPB_API_INLINE void upb_Arena_ShrinkLast(upb_Arena* a, void* ptr, size_t oldsize, size_t size); +#ifdef UPB_TRACING_ENABLED +void upb_Arena_SetTraceHandler(void (*initArenaTraceHandler)(const upb_Arena*, + size_t size), + void (*fuseArenaTraceHandler)(const upb_Arena*, + const upb_Arena*), + void (*freeArenaTraceHandler)(const upb_Arena*)); +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/upb/message/internal/message.c b/upb/message/internal/message.c index e5eb16e6e9..856fc97016 100644 --- a/upb/message/internal/message.c +++ b/upb/message/internal/message.c @@ -62,13 +62,13 @@ bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need, static void (*_new_message_trace_handler)(const upb_MiniTable*, const upb_Arena*); -void upb_Message_SetNewMessageTraceHandler( +void UPB_PRIVATE(upb_Message_SetNewMessageTraceHandler)( void (*new_message_trace_handler)(const upb_MiniTable*, const upb_Arena*)) { _new_message_trace_handler = new_message_trace_handler; } -void upb_Message_LogNewMessage(const upb_MiniTable* mini_table, - const upb_Arena* arena) { +void UPB_PRIVATE(upb_Message_LogNewMessage)(const upb_MiniTable* mini_table, + const upb_Arena* arena) { if (_new_message_trace_handler) { _new_message_trace_handler(mini_table, arena); } diff --git a/upb/message/internal/message.h b/upb/message/internal/message.h index 7f3686a28a..a81bb4f0b0 100644 --- a/upb/message/internal/message.h +++ b/upb/message/internal/message.h @@ -60,17 +60,17 @@ typedef struct upb_Message_Internal { } upb_Message_Internal; #ifdef UPB_TRACING_ENABLED -void upb_Message_SetNewMessageTraceHandler( +void UPB_PRIVATE(upb_Message_SetNewMessageTraceHandler)( void (*newMessageTraceHandler)(const upb_MiniTable*, const upb_Arena*)); -void upb_Message_LogNewMessage(const upb_MiniTable* mini_table, - const upb_Arena* arena); +void UPB_PRIVATE(upb_Message_LogNewMessage)(const upb_MiniTable* mini_table, + const upb_Arena* arena); #endif // Inline version upb_Message_New(), for internal use. UPB_INLINE struct upb_Message* _upb_Message_New(const upb_MiniTable* m, upb_Arena* a) { #ifdef UPB_TRACING_ENABLED - upb_Message_LogNewMessage(m, a); + UPB_PRIVATE(upb_Message_LogNewMessage)(m, a); #endif const int size = m->UPB_PRIVATE(size); struct upb_Message* msg = (struct upb_Message*)upb_Arena_Malloc(a, size); diff --git a/upb/message/map.h b/upb/message/map.h index 996bd6d502..c758a695ce 100644 --- a/upb/message/map.h +++ b/upb/message/map.h @@ -63,12 +63,6 @@ UPB_API_INLINE bool upb_Map_Set(upb_Map* map, upb_MessageValue key, UPB_API bool upb_Map_Delete(upb_Map* map, upb_MessageValue key, upb_MessageValue* val); -// (DEPRECATED and going away soon. Do not use.) -UPB_INLINE bool upb_Map_Delete2(upb_Map* map, upb_MessageValue key, - upb_MessageValue* val) { - return upb_Map_Delete(map, key, val); -} - // Map iteration: // // size_t iter = kUpb_Map_Begin; diff --git a/upb/message/message.h b/upb/message/message.h index 114aefb0a1..cbcca84a72 100644 --- a/upb/message/message.h +++ b/upb/message/message.h @@ -15,6 +15,7 @@ #include #include "upb/mem/arena.h" +#include "upb/message/internal/message.h" #include "upb/message/internal/types.h" #include "upb/mini_table/message.h" @@ -45,6 +46,18 @@ UPB_API void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m); // Returns whether a message has been frozen. UPB_API_INLINE bool upb_Message_IsFrozen(const upb_Message* msg); +#ifdef UPB_TRACING_ENABLED +UPB_INLINE void upb_Message_SetNewMessageTraceHandler( + void (*newMessageTraceHandler)(const upb_MiniTable* mini_table, + const upb_Arena* arena)) { + UPB_PRIVATE(upb_Message_SetNewMessageTraceHandler)(newMessageTraceHandler); +} +UPB_INLINE void upb_Message_LogNewMessage(const upb_MiniTable* mini_table, + const upb_Arena* arena) { + UPB_PRIVATE(upb_Message_LogNewMessage)(mini_table, arena); +} +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/upb/port/def.inc b/upb/port/def.inc index 1a41d45828..7d23d5c8b3 100644 --- a/upb/port/def.inc +++ b/upb/port/def.inc @@ -309,10 +309,10 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); /* Disable proto2 arena behavior (TEMPORARY) **********************************/ -#ifdef UPB_DISABLE_PROTO2_ENUM_CHECKING -#define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 1 +#ifdef UPB_DISABLE_CLOSED_ENUM_CHECKING +#define UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN 1 #else -#define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 0 +#define UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN 0 #endif #if defined(__cplusplus) diff --git a/upb/port/undef.inc b/upb/port/undef.inc index e4aec84b50..c715441fd1 100644 --- a/upb/port/undef.inc +++ b/upb/port/undef.inc @@ -45,7 +45,7 @@ #undef UPB_ASAN #undef UPB_ASAN_GUARD_SIZE #undef UPB_CLANG_ASAN -#undef UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 +#undef UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN #undef UPB_DEPRECATED #undef UPB_GNUC_MIN #undef UPB_DESCRIPTOR_UPB_H_FILENAME diff --git a/upb/reflection/def.hpp b/upb/reflection/def.hpp index 983ffbffe8..b3f172a8d1 100644 --- a/upb/reflection/def.hpp +++ b/upb/reflection/def.hpp @@ -18,6 +18,7 @@ #include "upb/base/status.hpp" #include "upb/base/string_view.h" #include "upb/mem/arena.hpp" +#include "upb/message/value.h" #include "upb/mini_descriptor/decode.h" #include "upb/mini_table/enum.h" #include "upb/mini_table/field.h" @@ -87,6 +88,9 @@ class FieldDefPtr { // been finalized. uint32_t index() const { return upb_FieldDef_Index(ptr_); } + // Index into msgdef->layout->fields or file->exts + uint32_t layout_index() const { return upb_FieldDef_LayoutIndex(ptr_); } + // The MessageDef to which this field belongs (for extensions, the extended // message). MessageDefPtr containing_type() const; @@ -201,6 +205,9 @@ class MessageDefPtr { const char* full_name() const { return upb_MessageDef_FullName(ptr_); } const char* name() const { return upb_MessageDef_Name(ptr_); } + // Returns the MessageDef that contains this MessageDef (or null). + MessageDefPtr containing_type() const; + const upb_MiniTable* mini_table() const { return upb_MessageDef_MiniTable(ptr_); } @@ -416,6 +423,9 @@ class EnumDefPtr { const char* name() const { return upb_EnumDef_Name(ptr_); } bool is_closed() const { return upb_EnumDef_IsClosed(ptr_); } + // Returns the MessageDef that contains this EnumDef (or null). + MessageDefPtr containing_type() const; + // The value that is used as the default when no field default is specified. // If not set explicitly, the first value that was added will be used. // The default value must be a member of the enum. @@ -570,6 +580,14 @@ inline FileDefPtr MessageDefPtr::file() const { return FileDefPtr(upb_MessageDef_File(ptr_)); } +inline MessageDefPtr MessageDefPtr::containing_type() const { + return MessageDefPtr(upb_MessageDef_ContainingType(ptr_)); +} + +inline MessageDefPtr EnumDefPtr::containing_type() const { + return MessageDefPtr(upb_EnumDef_ContainingType(ptr_)); +} + inline EnumDefPtr MessageDefPtr::enum_type(int i) const { return EnumDefPtr(upb_MessageDef_NestedEnum(ptr_, i)); } diff --git a/upb/reflection/def_pool.h b/upb/reflection/def_pool.h index 7ca02a88da..9a372876db 100644 --- a/upb/reflection/def_pool.h +++ b/upb/reflection/def_pool.h @@ -66,8 +66,8 @@ const upb_FieldDef* upb_DefPool_FindExtensionByNumber(const upb_DefPool* s, const upb_MessageDef* m, int32_t fieldnum); -const upb_ServiceDef* upb_DefPool_FindServiceByName(const upb_DefPool* s, - const char* name); +UPB_API const upb_ServiceDef* upb_DefPool_FindServiceByName( + const upb_DefPool* s, const char* name); const upb_ServiceDef* upb_DefPool_FindServiceByNameWithSize( const upb_DefPool* s, const char* name, size_t size); diff --git a/upb/reflection/enum_def.c b/upb/reflection/enum_def.c index de85cbd9b1..4a6b2408ae 100644 --- a/upb/reflection/enum_def.c +++ b/upb/reflection/enum_def.c @@ -160,7 +160,11 @@ const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i) { } bool upb_EnumDef_IsClosed(const upb_EnumDef* e) { - if (UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3) return false; + if (UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN) return false; + return upb_EnumDef_IsSpecifiedAsClosed(e); +} + +bool upb_EnumDef_IsSpecifiedAsClosed(const upb_EnumDef* e) { return UPB_DESC(FeatureSet_enum_type)(e->resolved_features) == UPB_DESC(FeatureSet_CLOSED); } diff --git a/upb/reflection/enum_def.h b/upb/reflection/enum_def.h index a81ce5fd11..197fb45144 100644 --- a/upb/reflection/enum_def.h +++ b/upb/reflection/enum_def.h @@ -33,6 +33,7 @@ UPB_API const upb_EnumValueDef* upb_EnumDef_FindValueByNumber( UPB_API const char* upb_EnumDef_FullName(const upb_EnumDef* e); bool upb_EnumDef_HasOptions(const upb_EnumDef* e); bool upb_EnumDef_IsClosed(const upb_EnumDef* e); +bool upb_EnumDef_IsSpecifiedAsClosed(const upb_EnumDef* e); // Creates a mini descriptor string for an enum, returns true on success. bool upb_EnumDef_MiniDescriptorEncode(const upb_EnumDef* e, upb_Arena* a, diff --git a/upb/reflection/enum_value_def.c b/upb/reflection/enum_value_def.c index b9b94c9dc9..0ede8463d3 100644 --- a/upb/reflection/enum_value_def.c +++ b/upb/reflection/enum_value_def.c @@ -113,15 +113,10 @@ static void create_enumvaldef(upb_DefBuilder* ctx, const char* prefix, static void _upb_EnumValueDef_CheckZeroValue(upb_DefBuilder* ctx, const upb_EnumDef* e, const upb_EnumValueDef* v, int n) { - if (upb_EnumDef_IsClosed(e) || n == 0 || v[0].number == 0) return; - - // When the special UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 is enabled, we have to - // exempt proto2 enums from this check, even when we are treating them as + // When the special UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN is enabled, we have to + // exempt closed enums from this check, even when we are treating them as // open. - if (UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 && - upb_FileDef_Syntax(upb_EnumDef_File(e)) == kUpb_Syntax_Proto2) { - return; - } + if (upb_EnumDef_IsSpecifiedAsClosed(e) || n == 0 || v[0].number == 0) return; _upb_DefBuilder_Errf(ctx, "for open enums, the first value must be zero (%s)", upb_EnumDef_FullName(e)); diff --git a/upb/reflection/field_def.c b/upb/reflection/field_def.c index 1a0a821451..38366566e6 100644 --- a/upb/reflection/field_def.c +++ b/upb/reflection/field_def.c @@ -122,6 +122,10 @@ upb_FieldType upb_FieldDef_Type(const upb_FieldDef* f) { uint32_t upb_FieldDef_Index(const upb_FieldDef* f) { return f->index_; } +uint32_t upb_FieldDef_LayoutIndex(const upb_FieldDef* f) { + return f->layout_index; +} + upb_Label upb_FieldDef_Label(const upb_FieldDef* f) { // TODO: remove once we can deprecate kUpb_Label_Required. if (UPB_DESC(FeatureSet_field_presence)(f->resolved_features) == diff --git a/upb/reflection/field_def.h b/upb/reflection/field_def.h index 5667141a0c..2923228ca8 100644 --- a/upb/reflection/field_def.h +++ b/upb/reflection/field_def.h @@ -14,6 +14,7 @@ #include "upb/base/descriptor_constants.h" #include "upb/base/string_view.h" +#include "upb/message/value.h" #include "upb/mini_table/extension.h" #include "upb/mini_table/field.h" #include "upb/reflection/common.h" @@ -55,6 +56,7 @@ bool upb_FieldDef_IsString(const upb_FieldDef* f); UPB_API bool upb_FieldDef_IsSubMessage(const upb_FieldDef* f); UPB_API const char* upb_FieldDef_JsonName(const upb_FieldDef* f); UPB_API upb_Label upb_FieldDef_Label(const upb_FieldDef* f); +uint32_t upb_FieldDef_LayoutIndex(const upb_FieldDef* f); UPB_API const upb_MessageDef* upb_FieldDef_MessageSubDef(const upb_FieldDef* f); bool _upb_FieldDef_ValidateUtf8(const upb_FieldDef* f); diff --git a/upb/reflection/method_def.h b/upb/reflection/method_def.h index 4abfb69e0f..082c509171 100644 --- a/upb/reflection/method_def.h +++ b/upb/reflection/method_def.h @@ -19,18 +19,19 @@ extern "C" { #endif -bool upb_MethodDef_ClientStreaming(const upb_MethodDef* m); +UPB_API bool upb_MethodDef_ClientStreaming(const upb_MethodDef* m); const char* upb_MethodDef_FullName(const upb_MethodDef* m); bool upb_MethodDef_HasOptions(const upb_MethodDef* m); int upb_MethodDef_Index(const upb_MethodDef* m); -const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m); -const char* upb_MethodDef_Name(const upb_MethodDef* m); -const UPB_DESC(MethodOptions) * upb_MethodDef_Options(const upb_MethodDef* m); +UPB_API const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m); +UPB_API const char* upb_MethodDef_Name(const upb_MethodDef* m); +UPB_API const UPB_DESC(MethodOptions) * + upb_MethodDef_Options(const upb_MethodDef* m); const UPB_DESC(FeatureSet) * upb_MethodDef_ResolvedFeatures(const upb_MethodDef* m); -const upb_MessageDef* upb_MethodDef_OutputType(const upb_MethodDef* m); -bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m); -const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m); +UPB_API const upb_MessageDef* upb_MethodDef_OutputType(const upb_MethodDef* m); +UPB_API bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m); +UPB_API const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m); #ifdef __cplusplus } /* extern "C" */ diff --git a/upb/reflection/service_def.h b/upb/reflection/service_def.h index 781932e176..da3f32afde 100644 --- a/upb/reflection/service_def.h +++ b/upb/reflection/service_def.h @@ -19,16 +19,17 @@ extern "C" { #endif -const upb_FileDef* upb_ServiceDef_File(const upb_ServiceDef* s); +UPB_API const upb_FileDef* upb_ServiceDef_File(const upb_ServiceDef* s); const upb_MethodDef* upb_ServiceDef_FindMethodByName(const upb_ServiceDef* s, const char* name); -const char* upb_ServiceDef_FullName(const upb_ServiceDef* s); +UPB_API const char* upb_ServiceDef_FullName(const upb_ServiceDef* s); bool upb_ServiceDef_HasOptions(const upb_ServiceDef* s); int upb_ServiceDef_Index(const upb_ServiceDef* s); -const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, int i); -int upb_ServiceDef_MethodCount(const upb_ServiceDef* s); +UPB_API const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, + int i); +UPB_API int upb_ServiceDef_MethodCount(const upb_ServiceDef* s); const char* upb_ServiceDef_Name(const upb_ServiceDef* s); -const UPB_DESC(ServiceOptions) * +UPB_API const UPB_DESC(ServiceOptions) * upb_ServiceDef_Options(const upb_ServiceDef* s); const UPB_DESC(FeatureSet) * upb_ServiceDef_ResolvedFeatures(const upb_ServiceDef* s); diff --git a/upb/text/encode.c b/upb/text/encode.c index e13d9f294c..ae894be5e3 100644 --- a/upb/text/encode.c +++ b/upb/text/encode.c @@ -230,12 +230,19 @@ static void txtenc_bytes(txtenc* e, upb_StringView data) { static void txtenc_field(txtenc* e, upb_MessageValue val, const upb_FieldDef* f) { txtenc_indent(e); - const upb_CType type = upb_FieldDef_CType(f); + const upb_CType ctype = upb_FieldDef_CType(f); const bool is_ext = upb_FieldDef_IsExtension(f); const char* full = upb_FieldDef_FullName(f); const char* name = upb_FieldDef_Name(f); - if (type == kUpb_CType_Message) { + if (ctype == kUpb_CType_Message) { +// begin:google_only +// // TODO: Turn this into a feature check and opensource it. +// if (upb_FieldDef_Type(f) == kUpb_FieldType_Group) { +// const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f); +// name = upb_MessageDef_Name(m); +// } +// end:google_only if (is_ext) { txtenc_printf(e, "[%s] {", full); } else { @@ -257,7 +264,7 @@ static void txtenc_field(txtenc* e, upb_MessageValue val, txtenc_printf(e, "%s: ", name); } - switch (type) { + switch (ctype) { case kUpb_CType_Bool: txtenc_putstr(e, val.bool_val ? "true" : "false"); break; diff --git a/upb_generator/protoc-gen-upb.cc b/upb_generator/protoc-gen-upb.cc index 2b0e9c30cb..47b47057c2 100644 --- a/upb_generator/protoc-gen-upb.cc +++ b/upb_generator/protoc-gen-upb.cc @@ -20,11 +20,13 @@ #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/strings/escaping.h" +#include "absl/strings/match.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_replace.h" #include "absl/strings/string_view.h" #include "absl/strings/substitute.h" #include "upb/base/descriptor_constants.h" +#include "upb/base/status.hpp" #include "upb/base/string_view.h" #include "upb/mini_table/field.h" #include "upb/reflection/def.hpp" @@ -314,8 +316,7 @@ void GenerateExtensionInHeader(const DefPoolPair& pools, upb::FieldDefPtr ext, // Message extensions also have a Msg_mutable_foo() accessor that will // create the sub-message if it doesn't already exist. - if (ext.ctype() == kUpb_CType_Message && - !UPB_DESC(MessageOptions_map_entry)(ext.containing_type().options())) { + if (ext.IsSubMessage()) { output( R"cc( UPB_INLINE struct $0* $1_mutable_$2(struct $3* msg, @@ -603,8 +604,7 @@ void GenerateGetters(upb::FieldDefPtr field, const DefPoolPair& pools, const Options& options, Output& output) { if (field.IsMap()) { GenerateMapGetters(field, pools, msg_name, field_names, options, output); - } else if (UPB_DESC(MessageOptions_map_entry)( - field.containing_type().options())) { + } else if (field.containing_type().mapentry()) { GenerateMapEntryGetters(field, msg_name, output); } else if (field.IsSequence()) { GenerateRepeatedGetters(field, pools, msg_name, field_names, options, @@ -773,8 +773,7 @@ void GenerateNonRepeatedSetters(upb::FieldDefPtr field, // Message fields also have a Msg_mutable_foo() accessor that will create // the sub-message if it doesn't already exist. - if (field.ctype() == kUpb_CType_Message && - !UPB_DESC(MessageOptions_map_entry)(field.containing_type().options())) { + if (field.IsSubMessage() && !field.containing_type().mapentry()) { output( R"cc( UPB_INLINE struct $0* $1_mutable_$2($1* msg, upb_Arena* arena) { @@ -811,7 +810,7 @@ void GenerateMessageInHeader(upb::MessageDefPtr message, Output& output) { output("/* $0 */\n\n", message.full_name()); std::string msg_name = ToCIdent(message.full_name()); - if (!UPB_DESC(MessageOptions_map_entry)(message.options())) { + if (!message.mapentry()) { GenerateMessageFunctionsInHeader(message, options, output); }